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