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