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 1: 44 switch (outChannels) { 45 case 2: 46 for (int32 i = 0; i < frames; i++) { 47 *outBuffer++ = *inBuffer; 48 *outBuffer++ = *inBuffer++; 49 } 50 break; 51 } 52 break; 53 case 2: 54 switch (outChannels) { 55 case 1: 56 for (int32 i = 0; i < frames; i++) { 57 *outBuffer++ 58 = (Type)((BigType)inBuffer[0] + inBuffer[1]) / 2; 59 inBuffer += 2; 60 } 61 break; 62 } 63 break; 64 } 65 } 66 67 68 status_t 69 AudioChannelConverter::Read(void* outBuffer, int64 pos, int64 frames) 70 { 71 TRACE("AudioChannelConverter::Read(%p, %Ld, %Ld)\n", outBuffer, pos, frames); 72 status_t error = InitCheck(); 73 if (error != B_OK) 74 return error; 75 pos += fOutOffset; 76 77 int32 inChannels = fSource->Format().u.raw_audio.channel_count; 78 int32 outChannels = fFormat.u.raw_audio.channel_count; 79 TRACE(" convert %ld -> %ld channels\n", inChannels, outChannels); 80 81 int32 inSampleSize = fSource->Format().u.raw_audio.format 82 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 83 int32 inFrameSize = inSampleSize * inChannels; 84 uint8* inBuffer = new (nothrow) uint8[inFrameSize * frames]; 85 86 TRACE(" fSource->Read()\n"); 87 status_t ret = fSource->Read(inBuffer, pos, frames); 88 if (ret != B_OK) { 89 delete[] inBuffer; 90 return ret; 91 } 92 93 // We know that both formats are the same except for channel count 94 switch (fFormat.u.raw_audio.format) { 95 case media_raw_audio_format::B_AUDIO_FLOAT: 96 convert<float, float>((float*)inBuffer, (float*)outBuffer, 97 inChannels, outChannels, frames); 98 break; 99 case media_raw_audio_format::B_AUDIO_INT: 100 convert<int32, int64>((int32*)inBuffer, (int32*)outBuffer, 101 inChannels, outChannels, frames); 102 break; 103 case media_raw_audio_format::B_AUDIO_SHORT: 104 convert<int16, int32>((int16*)inBuffer, (int16*)outBuffer, 105 inChannels, outChannels, frames); 106 break; 107 case media_raw_audio_format::B_AUDIO_UCHAR: 108 convert<uint8, uint16>((uint8*)inBuffer, (uint8*)outBuffer, 109 inChannels, outChannels, frames); 110 break; 111 case media_raw_audio_format::B_AUDIO_CHAR: 112 convert<int8, int16>((int8*)inBuffer, (int8*)outBuffer, 113 inChannels, outChannels, frames); 114 break; 115 } 116 117 delete[] inBuffer; 118 119 TRACE("AudioChannelConverter::Read() done: %s\n", strerror(ret)); 120 return ret; 121 } 122 123 124 status_t 125 AudioChannelConverter::InitCheck() const 126 { 127 status_t error = AudioReader::InitCheck(); 128 if (error == B_OK && !fSource) 129 error = B_NO_INIT; 130 return error; 131 } 132 133 134 AudioReader* 135 AudioChannelConverter::Source() const 136 { 137 return fSource; 138 } 139 140