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 13using 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 24template<typename Type, typename BigType> 25static void 26convert(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 73AudioChannelConverter::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 83AudioChannelConverter::~AudioChannelConverter() 84{ 85} 86 87 88bigtime_t 89AudioChannelConverter::InitialLatency() const 90{ 91 return fSource->InitialLatency(); 92} 93 94 95status_t 96AudioChannelConverter::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 151status_t 152AudioChannelConverter::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 161AudioReader* 162AudioChannelConverter::Source() const 163{ 164 return fSource; 165} 166 167