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 "AudioChannelConverter.h" 8 9 #include <new> 10 #include <stdio.h> 11 #include <string.h> 12 13 using std::nothrow; 14 15 16 //#define TRACE_AUDIO_CONVERTER 17 #ifdef TRACE_AUDIO_CONVERTER 18 # define TRACE(x...) printf(x) 19 #else 20 # define TRACE(x...) 21 #endif 22 23 24 template<typename Type, typename BigType> 25 static void 26 convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels, 27 int32 frames) 28 { 29 // TODO: more conversions! 30 switch (inChannels) { 31 case 0: 32 break; 33 case 1: 34 switch (outChannels) { 35 case 2: 36 for (int32 i = 0; i < frames; i++) { 37 *outBuffer++ = *inBuffer; 38 *outBuffer++ = *inBuffer++; 39 } 40 break; 41 } 42 break; 43 case 2: 44 switch (outChannels) { 45 case 1: 46 for (int32 i = 0; i < frames; i++) { 47 *outBuffer++ 48 = (Type)((BigType)inBuffer[0] + inBuffer[1]) / 2; 49 inBuffer += 2; 50 } 51 break; 52 } 53 break; 54 default: 55 switch (outChannels) { 56 case 2: 57 for (int32 i = 0; i < frames; i++) { 58 outBuffer[0] = inBuffer[0]; 59 outBuffer[1] = inBuffer[1]; 60 inBuffer += outChannels; 61 outBuffer += 2; 62 } 63 break; 64 } 65 break; 66 } 67 } 68 69 70 // #pragma mark - 71 72 73 AudioChannelConverter::AudioChannelConverter(AudioReader* source, 74 const media_format& format) 75 : AudioReader(format), 76 fSource(source) 77 { 78 // TODO: check the format and make sure everything matches 79 // except for channel count 80 } 81 82 83 AudioChannelConverter::~AudioChannelConverter() 84 { 85 } 86 87 88 bigtime_t 89 AudioChannelConverter::InitialLatency() const 90 { 91 return fSource->InitialLatency(); 92 } 93 94 95 status_t 96 AudioChannelConverter::Read(void* outBuffer, int64 pos, int64 frames) 97 { 98 TRACE("AudioChannelConverter::Read(%p, %lld, %lld)\n", outBuffer, pos, frames); 99 status_t error = InitCheck(); 100 if (error != B_OK) 101 return error; 102 pos += fOutOffset; 103 104 int32 inChannels = fSource->Format().u.raw_audio.channel_count; 105 int32 outChannels = fFormat.u.raw_audio.channel_count; 106 TRACE(" convert %ld -> %ld channels\n", inChannels, outChannels); 107 108 int32 inSampleSize = fSource->Format().u.raw_audio.format 109 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 110 int32 inFrameSize = inSampleSize * inChannels; 111 uint8* inBuffer = new (nothrow) uint8[inFrameSize * frames]; 112 113 TRACE(" fSource->Read()\n"); 114 status_t ret = fSource->Read(inBuffer, pos, frames); 115 if (ret != B_OK) { 116 delete[] inBuffer; 117 return ret; 118 } 119 120 // We know that both formats are the same except for channel count 121 switch (fFormat.u.raw_audio.format) { 122 case media_raw_audio_format::B_AUDIO_FLOAT: 123 convert<float, float>((float*)inBuffer, (float*)outBuffer, 124 inChannels, outChannels, frames); 125 break; 126 case media_raw_audio_format::B_AUDIO_INT: 127 convert<int32, int64>((int32*)inBuffer, (int32*)outBuffer, 128 inChannels, outChannels, frames); 129 break; 130 case media_raw_audio_format::B_AUDIO_SHORT: 131 convert<int16, int32>((int16*)inBuffer, (int16*)outBuffer, 132 inChannels, outChannels, frames); 133 break; 134 case media_raw_audio_format::B_AUDIO_UCHAR: 135 convert<uint8, uint16>((uint8*)inBuffer, (uint8*)outBuffer, 136 inChannels, outChannels, frames); 137 break; 138 case media_raw_audio_format::B_AUDIO_CHAR: 139 convert<int8, int16>((int8*)inBuffer, (int8*)outBuffer, 140 inChannels, outChannels, frames); 141 break; 142 } 143 144 delete[] inBuffer; 145 146 TRACE("AudioChannelConverter::Read() done: %s\n", strerror(ret)); 147 return ret; 148 } 149 150 151 status_t 152 AudioChannelConverter::InitCheck() const 153 { 154 status_t error = AudioReader::InitCheck(); 155 if (error == B_OK && !fSource) 156 error = B_NO_INIT; 157 return error; 158 } 159 160 161 AudioReader* 162 AudioChannelConverter::Source() const 163 { 164 return fSource; 165 } 166 167