summaryrefslogtreecommitdiffstats
path: root/flow/bytestreamtoaudio_impl.cc
blob: de9ef7c51f7be4c41e56fa309e972eb5abd79da7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    /*

    Copyright (C) 2000 Stefan Westerfeld
                       [email protected]

    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);

}