~marcustomlinson/dspatchables/trunk

« back to all changes in this revision

Viewing changes to DspWaveStreamer/DspWaveStreamer.cpp

  • Committer: Marcus Tomlinson
  • Date: 2015-04-05 22:25:24 UTC
  • mfrom: (1.1.10 trunk)
  • Revision ID: marcus.tomlinson@canonical.com-20150405222524-urntp725s5hbk2im
Merged add_basic_components

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************
 
2
DSPatch - Cross-Platform, Object-Oriented, Flow-Based Programming Library
 
3
Copyright (c) 2012-2015 Marcus Tomlinson
 
4
 
 
5
This file is part of DSPatch.
 
6
 
 
7
GNU Lesser General Public License Usage
 
8
This file may be used under the terms of the GNU Lesser General Public
 
9
License version 3.0 as published by the Free Software Foundation and
 
10
appearing in the file LGPLv3.txt included in the packaging of this
 
11
file. Please review the following information to ensure the GNU Lesser
 
12
General Public License version 3.0 requirements will be met:
 
13
http://www.gnu.org/copyleft/lgpl.html.
 
14
 
 
15
Other Usage
 
16
Alternatively, this file may be used in accordance with the terms and
 
17
conditions contained in a signed written agreement between you and
 
18
Marcus Tomlinson.
 
19
 
 
20
DSPatch is distributed in the hope that it will be useful,
 
21
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
23
************************************************************************/
 
24
 
 
25
#include <DspWaveStreamer.h>
 
26
 
 
27
#include <fstream>
 
28
#include <iostream>
 
29
#include <string.h>
 
30
 
 
31
//=================================================================================================
 
32
 
 
33
DspWaveStreamer::DspWaveStreamer()
 
34
    : _waveData(0)
 
35
    , _bufferSize(256)
 
36
    , _sampleIndex(0)
 
37
    , _shortToFloatCoeff(1.0f / 32767.0f)
 
38
{
 
39
    _waveFormat.Clear();
 
40
 
 
41
    _leftChannel.resize(_bufferSize);
 
42
    _rightChannel.resize(_bufferSize);
 
43
 
 
44
    AddOutput_();
 
45
    AddOutput_();
 
46
    AddOutput_("Sample Rate");
 
47
 
 
48
    pFilePath = AddParameter_("filePath", DspParameter(DspParameter::FilePath, ""));
 
49
    pPlay = AddParameter_("play", DspParameter(DspParameter::Trigger));
 
50
    pPause = AddParameter_("pause", DspParameter(DspParameter::Trigger));
 
51
    pStop = AddParameter_("stop", DspParameter(DspParameter::Trigger));
 
52
    pIsPlaying = AddParameter_("isPlaying", DspParameter(DspParameter::Bool, false));
 
53
}
 
54
 
 
55
//-------------------------------------------------------------------------------------------------
 
56
 
 
57
DspWaveStreamer::~DspWaveStreamer()
 
58
{
 
59
}
 
60
 
 
61
//=================================================================================================
 
62
 
 
63
bool DspWaveStreamer::LoadFile(char const* filePath)
 
64
{
 
65
    bool wasPlaying = IsPlaying();
 
66
    Stop();
 
67
 
 
68
    if (filePath == NULL)
 
69
    {
 
70
        return false;
 
71
    }
 
72
 
 
73
    std::ifstream inFile(filePath, std::ios::binary | std::ios::in);
 
74
    if (inFile.bad())
 
75
    {
 
76
        return false;
 
77
    }
 
78
 
 
79
    int dwFileSize = 0, dwChunkSize = 0;
 
80
    char dwChunkId[5];
 
81
    char dwExtra[5];
 
82
 
 
83
    dwChunkId[4] = 0;
 
84
    dwExtra[4] = 0;
 
85
 
 
86
    // look for 'RIFF' chunk identifier
 
87
    inFile.seekg(0, std::ios::beg);
 
88
    inFile.read(dwChunkId, 4);
 
89
    if (strcmp(dwChunkId, "RIFF"))
 
90
    {
 
91
        std::cerr << "'" << filePath << "' not found.\n";
 
92
        inFile.close();
 
93
        return false;
 
94
    }
 
95
    inFile.seekg(4, std::ios::beg);  // get file size
 
96
    inFile.read(reinterpret_cast<char*>(&dwFileSize), 4);
 
97
    if (dwFileSize <= 16)
 
98
    {
 
99
        inFile.close();
 
100
        return false;
 
101
    }
 
102
    inFile.seekg(8, std::ios::beg);  // get file format
 
103
    inFile.read(dwExtra, 4);
 
104
    if (strcmp(dwExtra, "WAVE"))
 
105
    {
 
106
        inFile.close();
 
107
        return false;
 
108
    }
 
109
 
 
110
    // look for 'fmt ' chunk id
 
111
    bool bFilledFormat = false;
 
112
    for (int i = 12; i < dwFileSize;)
 
113
    {
 
114
        inFile.seekg(i, std::ios::beg);
 
115
        inFile.read(dwChunkId, 4);
 
116
        inFile.seekg(i + 4, std::ios::beg);
 
117
        inFile.read(reinterpret_cast<char*>(&dwChunkSize), 4);
 
118
        if (!strcmp(dwChunkId, "fmt "))
 
119
        {
 
120
            inFile.seekg(i + 8, std::ios::beg);
 
121
 
 
122
            _waveFormat.Clear();
 
123
            inFile.read(reinterpret_cast<char*>(&_waveFormat.format), 2);
 
124
            inFile.read(reinterpret_cast<char*>(&_waveFormat.channelCount), 2);
 
125
            inFile.read(reinterpret_cast<char*>(&_waveFormat.sampleRate), 4);
 
126
            inFile.read(reinterpret_cast<char*>(&_waveFormat.byteRate), 4);
 
127
            inFile.read(reinterpret_cast<char*>(&_waveFormat.frameSize), 2);
 
128
            inFile.read(reinterpret_cast<char*>(&_waveFormat.bitDepth), 2);
 
129
            inFile.read(reinterpret_cast<char*>(&_waveFormat.extraDataSize), 2);
 
130
 
 
131
            bFilledFormat = true;
 
132
            break;
 
133
        }
 
134
        dwChunkSize += 8;  // add offsets of the chunk id, and chunk size data entries
 
135
        dwChunkSize += 1;
 
136
        dwChunkSize &= 0xfffffffe;  // guarantees WORD padding alignment
 
137
        i += dwChunkSize;
 
138
    }
 
139
    if (!bFilledFormat)
 
140
    {
 
141
        inFile.close();
 
142
        return false;
 
143
    }
 
144
 
 
145
    // look for 'data' chunk id
 
146
    bool bFilledData = false;
 
147
    for (int i = 12; i < dwFileSize;)
 
148
    {
 
149
        inFile.seekg(i, std::ios::beg);
 
150
        inFile.read(dwChunkId, 4);
 
151
        inFile.seekg(i + 4, std::ios::beg);
 
152
        inFile.read(reinterpret_cast<char*>(&dwChunkSize), 4);
 
153
        if (!strcmp(dwChunkId, "data"))
 
154
        {
 
155
            _waveData.resize(dwChunkSize / 2);
 
156
            inFile.seekg(i + 8, std::ios::beg);
 
157
            inFile.read(reinterpret_cast<char*>(&_waveData[0]), dwChunkSize);
 
158
            bFilledData = true;
 
159
            break;
 
160
        }
 
161
        dwChunkSize += 8;  // add offsets of the chunk id, and chunk size data entries
 
162
        dwChunkSize += 1;
 
163
        dwChunkSize &= 0xfffffffe;  // guarantees WORD padding alignment
 
164
        i += dwChunkSize;
 
165
    }
 
166
    if (!bFilledData)
 
167
    {
 
168
        inFile.close();
 
169
        return false;
 
170
    }
 
171
 
 
172
    inFile.close();
 
173
 
 
174
    if (wasPlaying)
 
175
    {
 
176
        Play();
 
177
    }
 
178
 
 
179
    SetParameter_(pFilePath, DspParameter(DspParameter::FilePath, filePath));
 
180
    return true;
 
181
}
 
182
 
 
183
//-------------------------------------------------------------------------------------------------
 
184
 
 
185
void DspWaveStreamer::Play()
 
186
{
 
187
    SetParameter_(pIsPlaying, DspParameter(DspParameter::Bool, true));
 
188
}
 
189
 
 
190
//-------------------------------------------------------------------------------------------------
 
191
 
 
192
void DspWaveStreamer::Pause()
 
193
{
 
194
    SetParameter_(pIsPlaying, DspParameter(DspParameter::Bool, false));
 
195
}
 
196
 
 
197
//-------------------------------------------------------------------------------------------------
 
198
 
 
199
void DspWaveStreamer::Stop()
 
200
{
 
201
    _busyMutex.Lock();
 
202
 
 
203
    _sampleIndex = 0;
 
204
    SetParameter_(pIsPlaying, DspParameter(DspParameter::Bool, false));
 
205
 
 
206
    _busyMutex.Unlock();
 
207
}
 
208
 
 
209
//-------------------------------------------------------------------------------------------------
 
210
 
 
211
bool DspWaveStreamer::IsPlaying() const
 
212
{
 
213
    return *GetParameter_(pIsPlaying)->GetBool();
 
214
}
 
215
 
 
216
//=================================================================================================
 
217
 
 
218
void DspWaveStreamer::Process_(DspSignalBus&, DspSignalBus& outputs)
 
219
{
 
220
    if (IsPlaying() && _waveData.size() > 0)
 
221
    {
 
222
        _busyMutex.Lock();
 
223
 
 
224
        int index = 0;
 
225
        for (int i = 0; i < _bufferSize * 2; i += 2)
 
226
        {
 
227
            _leftChannel[index++] = (float)_waveData[_sampleIndex + i] * _shortToFloatCoeff;
 
228
        }
 
229
 
 
230
        index = 0;
 
231
        for (int i = 1; i < _bufferSize * 2; i += 2)
 
232
        {
 
233
            _rightChannel[index++] = (float)_waveData[_sampleIndex + i] * _shortToFloatCoeff;
 
234
        }
 
235
 
 
236
        _sampleIndex += _bufferSize * 2;
 
237
        _sampleIndex %= _waveData.size() - _bufferSize * 2;
 
238
 
 
239
        _busyMutex.Unlock();
 
240
 
 
241
        outputs.SetValue(0, _leftChannel);
 
242
        outputs.SetValue(1, _rightChannel);
 
243
        outputs.SetValue("Sample Rate", _waveFormat.sampleRate);
 
244
    }
 
245
    else
 
246
    {
 
247
        outputs.ClearValue(0);
 
248
        outputs.ClearValue(1);
 
249
    }
 
250
}
 
251
 
 
252
//-------------------------------------------------------------------------------------------------
 
253
 
 
254
bool DspWaveStreamer::ParameterUpdating_(int index, DspParameter const& param)
 
255
{
 
256
    if (index == pFilePath)
 
257
    {
 
258
        return LoadFile(param.GetString()->c_str());
 
259
    }
 
260
    else if (index == pPlay)
 
261
    {
 
262
        Play();
 
263
        return true;
 
264
    }
 
265
    else if (index == pPause)
 
266
    {
 
267
        Pause();
 
268
        return true;
 
269
    }
 
270
    else if (index == pStop)
 
271
    {
 
272
        Stop();
 
273
        return true;
 
274
    }
 
275
 
 
276
    return false;
 
277
}
 
278
 
 
279
//=================================================================================================