|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2000 Stefan Westerfeld
|
|
|
|
stefan@space.twc.de
|
|
|
|
|
|
|
|
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 "resample.h"
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Arts;
|
|
|
|
|
|
|
|
namespace Arts {
|
|
|
|
|
|
|
|
class PacketRefiller : public Refiller {
|
|
|
|
protected:
|
|
|
|
queue< DataPacket<mcopbyte>* > inqueue;
|
|
|
|
int pos;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PacketRefiller() : pos(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void process(DataPacket<mcopbyte>* packet)
|
|
|
|
{
|
|
|
|
inqueue.push(packet);
|
|
|
|
}
|
|
|
|
unsigned long read(unsigned char *buffer, unsigned long bytes)
|
|
|
|
{
|
|
|
|
unsigned long done = 0;
|
|
|
|
while(!inqueue.empty())
|
|
|
|
{
|
|
|
|
long tocopy = bytes - done;
|
|
|
|
if(tocopy == 0) return bytes; /* complete? */
|
|
|
|
|
|
|
|
DataPacket<mcopbyte> *packet = inqueue.front();
|
|
|
|
if(tocopy > (packet->size - pos))
|
|
|
|
tocopy = (packet->size - pos);
|
|
|
|
|
|
|
|
memcpy(&buffer[done],&packet->contents[pos],tocopy);
|
|
|
|
pos += tocopy;
|
|
|
|
done += tocopy;
|
|
|
|
|
|
|
|
if(pos == packet->size) {
|
|
|
|
packet->processed();
|
|
|
|
pos = 0;
|
|
|
|
inqueue.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class ByteStreamToAudio_impl : public ByteStreamToAudio_skel,
|
|
|
|
public StdSynthModule
|
|
|
|
{
|
|
|
|
PacketRefiller refiller;
|
|
|
|
Resampler resampler;
|
|
|
|
long _samplingRate, _channels, _bits;
|
|
|
|
public:
|
|
|
|
ByteStreamToAudio_impl() :resampler(&refiller),
|
|
|
|
_samplingRate(44100), _channels(2), _bits(16)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
long samplingRate() { return _samplingRate; }
|
|
|
|
void samplingRate(long newRate) {
|
|
|
|
_samplingRate = newRate;
|
|
|
|
resampler.setStep((float)_samplingRate / samplingRateFloat);
|
|
|
|
}
|
|
|
|
|
|
|
|
long channels() { return _channels; }
|
|
|
|
void channels(long newChannels) {
|
|
|
|
_channels = newChannels;
|
|
|
|
resampler.setChannels(_channels);
|
|
|
|
}
|
|
|
|
|
|
|
|
long bits() { return _bits; }
|
|
|
|
void bits(long newBits) {
|
|
|
|
_bits = newBits;
|
|
|
|
resampler.setBits(_bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool running() { return !resampler.underrun(); }
|
|
|
|
|
|
|
|
void process_indata(DataPacket<mcopbyte> *packet)
|
|
|
|
{
|
|
|
|
refiller.process(packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
void calculateBlock(unsigned long samples)
|
|
|
|
{
|
|
|
|
resampler.run(left,right,samples);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
REGISTER_IMPLEMENTATION(ByteStreamToAudio_impl);
|
|
|
|
|
|
|
|
}
|