vfs: check userland buffers before reading them.
[haiku.git] / src / apps / mediaplayer / media_node_framework / audio / AudioChannelConverter.cpp
blobffca357d76e32ac8ae158006a55930fc560a675c
1 /*
2 * Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT licensce.
4 */
7 #include "AudioChannelConverter.h"
9 #include <new>
10 #include <stdio.h>
11 #include <string.h>
13 using std::nothrow;
16 //#define TRACE_AUDIO_CONVERTER
17 #ifdef TRACE_AUDIO_CONVERTER
18 # define TRACE(x...) printf(x)
19 #else
20 # define TRACE(x...)
21 #endif
24 template<typename Type, typename BigType>
25 static void
26 convert(Type* inBuffer, Type* outBuffer, int32 inChannels, int32 outChannels,
27 int32 frames)
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++;
40 break;
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;
51 break;
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;
63 break;
65 break;
70 // #pragma mark -
73 AudioChannelConverter::AudioChannelConverter(AudioReader* source,
74 const media_format& format)
75 : AudioReader(format),
76 fSource(source)
78 // TODO: check the format and make sure everything matches
79 // except for channel count
83 AudioChannelConverter::~AudioChannelConverter()
88 bigtime_t
89 AudioChannelConverter::InitialLatency() const
91 return fSource->InitialLatency();
95 status_t
96 AudioChannelConverter::Read(void* outBuffer, int64 pos, int64 frames)
98 TRACE("AudioChannelConverter::Read(%p, %Ld, %Ld)\n", outBuffer, pos, frames);
99 status_t error = InitCheck();
100 if (error != B_OK)
101 return error;
102 pos += fOutOffset;
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);
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];
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;
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;
144 delete[] inBuffer;
146 TRACE("AudioChannelConverter::Read() done: %s\n", strerror(ret));
147 return ret;
151 status_t
152 AudioChannelConverter::InitCheck() const
154 status_t error = AudioReader::InitCheck();
155 if (error == B_OK && !fSource)
156 error = B_NO_INIT;
157 return error;
161 AudioReader*
162 AudioChannelConverter::Source() const
164 return fSource;