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