diff options
Diffstat (limited to 'flow/audiotobytestream_impl.cpp')
-rw-r--r-- | flow/audiotobytestream_impl.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/flow/audiotobytestream_impl.cpp b/flow/audiotobytestream_impl.cpp new file mode 100644 index 0000000..a48fe8a --- /dev/null +++ b/flow/audiotobytestream_impl.cpp @@ -0,0 +1,223 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + 2001, 2003 Matthias Kretz + kretz@kde.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "artsflow.h" +#include "stdsynthmodule.h" +#include "debug.h" + +#include <vector> +#include <iostream> +#include <math.h> + +#undef DEBUG_MESSAGES + +using namespace std; +using namespace Arts; + +namespace Arts { + +class AudioToByteStream_impl : public AudioToByteStream_skel, + public StdSynthModule +{ + long _samplingRate, _channels, _bits; + long sampleSize; + double step; + bool interpolate; + vector<float> leftbuffer; + vector<float> rightbuffer; + int range; + double _pos; +protected: + void updateSampleSize() + { + sampleSize = _channels * _bits / 8; + } + +public: + AudioToByteStream_impl() : + _pos(0) + { + samplingRate(44100); + channels(2); + bits(16); + } + + long samplingRate() { return _samplingRate; } + void samplingRate(long newRate) { + double newStep = samplingRateFloat / (float)newRate; + arts_return_if_fail(newStep > 0); + _samplingRate = newRate; + step = newStep; + + double delta = step - floor(step); + interpolate = fabs(delta) > 0.001; +#ifdef DEBUG_MESSAGES + arts_debug( "samplingRate(%i): step = %e, delta = %e, interpolate: %i", newRate, step, delta, interpolate ); +#endif + } + + long channels() { return _channels; } + void channels(long newChannels) { + arts_return_if_fail(newChannels == 1 || newChannels == 2); + _channels = newChannels; + updateSampleSize(); + } + + long bits() { return _bits; } + void bits(long newBits) { + arts_return_if_fail(newBits == 8 || newBits == 16); + _bits = newBits; + range = (newBits == 8 ) ? 128 : 32768; + updateSampleSize(); + } + + void calculateBlock(unsigned long samples) + { + leftbuffer.resize( 1 + samples ); + rightbuffer.resize( 1 + samples ); + for( unsigned long i = 0; i < samples; ++i ) { + leftbuffer[1 + i] = (left[i] > 1.0f) ? 1.0f : (left[i] < -1.0f) ? -1.0f : left[i]; + rightbuffer[1 + i] = (right[i] > 1.0f) ? 1.0f : (right[i] < -1.0f) ? -1.0f : right[i]; + } + + int samplestosend = (int)ceil(leftbuffer.size() / step); + DataPacket<mcopbyte> *packet = outdata.allocPacket( samplestosend * sampleSize ); +#ifdef DEBUG_MESSAGES + arts_debug( "calculateBlock(%i): send %i samples", samples, samplestosend ); +#endif + + int processed = 0; + if( interpolate ) { + double pos = 0; + if( _channels == 2 ) { + if( _bits == 16 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + double error = modf(_pos, &pos); + int intpos = (int)pos; +#ifdef DEBUG_MESSAGES + arts_debug( "pos=%i, error=%e", intpos, error ); +#endif + long leftchannel = long((leftbuffer[intpos] * (1.0 - error) + leftbuffer[intpos + 1] * error) * 32768) + 32768; + long rightchannel = long((rightbuffer[intpos] * (1.0 - error) + rightbuffer[intpos + 1] * error) * 32768) + 32768; + packet->contents[processed ] = leftchannel; + packet->contents[processed + 1] = (leftchannel >> 8) - 128; + packet->contents[processed + 2] = rightchannel; + packet->contents[processed + 3] = (rightchannel >> 8) - 128; + _pos += step; + processed += 4; + } + } else if( _bits == 8 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + double error = modf(_pos, &pos); + int intpos = (int)pos; + long leftchannel = long((leftbuffer[intpos] * (1.0 - error) + leftbuffer[intpos + 1] * error) * 128) + 128; + long rightchannel = long((rightbuffer[intpos] * (1.0 - error) + rightbuffer[intpos + 1] * error) * 128) + 128; + packet->contents[processed ] = leftchannel; + packet->contents[processed + 1] = rightchannel; + _pos += step; + processed += 2; + } + } + } else { + if( _bits == 16 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + double error = modf(_pos, &pos); + int intpos = (int)pos; + long leftchannel = long(((leftbuffer[intpos] + rightbuffer[intpos]) * (1.0 - error) + (leftbuffer[intpos + 1] + rightbuffer[intpos + 1]) * error) * 16384) + 32768; + packet->contents[processed ] = leftchannel; + packet->contents[processed + 1] = (leftchannel >> 8) - 128; + _pos += step; + processed += 2; + } + } else if( _bits == 8 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + double error = modf(_pos, &pos); + int intpos = (int)pos; + long leftchannel = long(((leftbuffer[intpos] + rightbuffer[intpos]) * (1.0 - error) + (leftbuffer[intpos + 1] + rightbuffer[intpos + 1]) * error) * 64) + 128; + packet->contents[processed] = leftchannel; + _pos += step; + ++processed; + } + } + } + } else { + if( _channels == 2 ) { + if( _bits == 16 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + int intpos = (int)_pos; + long leftchannel = long(leftbuffer[intpos] * 32768) + 32768; + long rightchannel = long(rightbuffer[intpos] * 32768) + 32768; + packet->contents[processed ] = leftchannel; + packet->contents[processed + 1] = (leftchannel >> 8) - 128; + packet->contents[processed + 2] = rightchannel; + packet->contents[processed + 3] = (rightchannel >> 8) - 128; + _pos += step; + processed += 4; + } + } else if( _bits == 8 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + int intpos = (int)_pos; + long leftchannel = long(leftbuffer[intpos] * 128) + 128; + long rightchannel = long(rightbuffer[intpos] * 128) + 128; + packet->contents[processed ] = leftchannel; + packet->contents[processed + 1] = rightchannel; + _pos += step; + processed += 2; + } + } + } else { + if( _bits == 16 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + int intpos = (int)_pos; + long leftchannel = long((leftbuffer[intpos] + rightbuffer[intpos]) * 16384) + 32768; + packet->contents[processed ] = leftchannel; + packet->contents[processed + 1] = (leftchannel >> 8) - 128; + _pos += step; + processed += 2; + } + } else if( _bits == 8 ) { + while( _pos < (double)leftbuffer.size() - 1 ) { + int intpos = (int)_pos; + long leftchannel = long((leftbuffer[intpos] + rightbuffer[intpos]) * 64) + 128; + packet->contents[processed] = leftchannel; + _pos += step; + ++processed; + } + } + } + } + leftbuffer[0] = leftbuffer.back(); + rightbuffer[0] = rightbuffer.back(); + _pos = _pos - floor(_pos); + packet->size = processed; + packet->send(); +#ifdef DEBUG_MESSAGES + arts_debug( "calculateBlock(%i): %i samples sent, _pos = %e", samples, processed / sampleSize, _pos ); +#endif + } +}; + +REGISTER_IMPLEMENTATION(AudioToByteStream_impl); + +} |