1 /* 2 * Copyright © 2008 Stephan Aßmus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT licensce. 4 */ 5 6 #include "AudioVolumeConverter.h" 7 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <MediaDefs.h> 12 13 14 //#define TRACE_AUDIO_CONVERTER 15 #ifdef TRACE_AUDIO_CONVERTER 16 # define TRACE(x...) printf(x) 17 #else 18 # define TRACE(x...) 19 #endif 20 21 22 AudioVolumeConverter::AudioVolumeConverter(AudioReader* source, float volume) 23 : AudioReader(), 24 fSource(NULL), 25 fVolume(volume), 26 fPreviousVolume(volume) 27 { 28 if (source && source->Format().type == B_MEDIA_RAW_AUDIO) 29 fFormat = source->Format(); 30 else 31 source = NULL; 32 fSource = source; 33 } 34 35 36 AudioVolumeConverter::~AudioVolumeConverter() 37 { 38 } 39 40 41 template<typename SampleType> 42 static void 43 convert(SampleType* buffer, const int32 samples, const float volume, 44 const float rounding) 45 { 46 for (int32 i = 0; i < samples; i++) { 47 *buffer = (SampleType)(*buffer * volume + rounding); 48 buffer++; 49 } 50 } 51 52 53 template<typename SampleType> 54 static void 55 convert(SampleType* buffer, const int32 frames, const int32 channels, 56 const float volume1, const float volume2, const float rounding) 57 { 58 float volumeDiff = volume2 - volume1; 59 for (int32 i = 0; i < frames; i++) { 60 float volume = volume1 + volumeDiff * (i / (frames - 1)); 61 for (int32 k = 0; k < channels; k++) { 62 *buffer = (SampleType)(*buffer * volume + rounding); 63 buffer++; 64 } 65 } 66 } 67 68 69 status_t 70 AudioVolumeConverter::Read(void* buffer, int64 pos, int64 frames) 71 { 72 TRACE("AudioVolumeConverter::Read(%p, %lld, %lld)\n", buffer, pos, frames); 73 status_t error = InitCheck(); 74 if (error != B_OK) { 75 TRACE("AudioVolumeConverter::Read() done 1\n"); 76 return error; 77 } 78 pos += fOutOffset; 79 80 status_t ret = fSource->Read(buffer, pos, frames); 81 if (fPreviousVolume == 1.0 && fVolume == 1.0) { 82 TRACE("AudioVolumeConverter::Read() done 2\n"); 83 return ret; 84 } 85 86 int32 channelCount = fFormat.u.raw_audio.channel_count; 87 int32 samples = frames * channelCount; 88 89 // apply volume 90 switch (fSource->Format().u.raw_audio.format) { 91 case media_raw_audio_format::B_AUDIO_FLOAT: 92 if (fVolume != fPreviousVolume) { 93 convert((float*)buffer, frames, channelCount, 94 fPreviousVolume, fVolume, 0.0); 95 } else 96 convert((float*)buffer, samples, fVolume, 0.0); 97 break; 98 case media_raw_audio_format::B_AUDIO_INT: 99 if (fVolume != fPreviousVolume) { 100 convert((int32*)buffer, frames, channelCount, 101 fPreviousVolume, fVolume, 0.5); 102 } else 103 convert((int32*)buffer, samples, fVolume, 0.5); 104 break; 105 case media_raw_audio_format::B_AUDIO_SHORT: 106 if (fVolume != fPreviousVolume) { 107 convert((int16*)buffer, frames, channelCount, 108 fPreviousVolume, fVolume, 0.5); 109 } else 110 convert((int16*)buffer, samples, fVolume, 0.5); 111 break; 112 case media_raw_audio_format::B_AUDIO_UCHAR: { 113 // handle this extra, because center != 0 114 // (also ignores ramping the volume) 115 uchar* b = (uchar*)buffer; 116 for (int32 i = 0; i < samples; i++) { 117 *b = (uchar)(((float)*b - 128) * fVolume + 128.5); 118 b++; 119 } 120 break; 121 } 122 case media_raw_audio_format::B_AUDIO_CHAR: 123 if (fVolume != fPreviousVolume) { 124 convert((int8*)buffer, frames, channelCount, 125 fPreviousVolume, fVolume, 0.0); 126 } else 127 convert((int8*)buffer, samples, fVolume, 0.5); 128 break; 129 } 130 131 fPreviousVolume = fVolume; 132 133 TRACE("AudioVolumeConverter::Read() done\n"); 134 return B_OK; 135 } 136 137 138 status_t 139 AudioVolumeConverter::InitCheck() const 140 { 141 status_t error = AudioReader::InitCheck(); 142 if (error == B_OK && !fSource) 143 error = B_NO_INIT; 144 if (error == B_OK) 145 error = fSource->InitCheck(); 146 return error; 147 } 148 149 150 AudioReader* 151 AudioVolumeConverter::Source() const 152 { 153 return fSource; 154 } 155 156 157 void 158 AudioVolumeConverter::SetVolume(float volume) 159 { 160 fVolume = volume; 161 } 162 163 164 float 165 AudioVolumeConverter::Volume() const 166 { 167 return fVolume; 168 } 169 170