You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/flow/audiotobytestream_impl.cc

224 lines
7.2 KiB

/*
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);
}