xref: /haiku/src/apps/mediaplayer/media_node_framework/audio/AudioChannelConverter.cpp (revision c9ad965c81b08802fed0827fd1dd16f45297928a)
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