Skip to content

Commit 8427444

Browse files
committed
Tonie Audio Player (not working!)
1 parent d6ec73c commit 8427444

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

AudioGeneratorTonie.cpp

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
AudioGeneratorTonie
3+
Audio output generator that plays Opus audio files
4+
5+
Copyright (C) 2020 Earle F. Philhower, III
6+
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation, either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#include "AudioGeneratorTonie.h"
22+
23+
AudioGeneratorTonie::AudioGeneratorTonie()
24+
{
25+
of = nullptr;
26+
buff = nullptr;
27+
buffPtr = 0;
28+
buffLen = 0;
29+
running = false;
30+
}
31+
32+
AudioGeneratorTonie::~AudioGeneratorTonie()
33+
{
34+
if (of) op_free(of);
35+
of = nullptr;
36+
free(buff);
37+
buff = nullptr;
38+
}
39+
40+
#define OPUS_BUFF 512
41+
42+
bool AudioGeneratorTonie::begin(AudioFileSource *source, AudioOutput *output)
43+
{
44+
buff = (int16_t*)malloc(OPUS_BUFF * sizeof(int16_t));
45+
if (!buff) return false;
46+
47+
if (!source) return false;
48+
file = source;
49+
if (!output) return false;
50+
this->output = output;
51+
if (!file->isOpen()) return false; // Error
52+
53+
//TODO?
54+
file->seek(4096, SEEK_CUR); //skip first sector
55+
56+
of = op_open_callbacks((void*)this, &cb, nullptr, 0, nullptr);
57+
if (!of) return false;
58+
59+
prev_li = -1;
60+
lastSample[0] = 0;
61+
lastSample[1] = 0;
62+
63+
buffPtr = 0;
64+
buffLen = 0;
65+
66+
output->begin();
67+
68+
// These are fixed by Opus
69+
output->SetRate(48000);
70+
output->SetBitsPerSample(16);
71+
output->SetChannels(2);
72+
73+
running = true;
74+
return true;
75+
}
76+
77+
bool AudioGeneratorTonie::loop()
78+
{
79+
80+
if (!running) goto done;
81+
82+
if (!output->ConsumeSample(lastSample)) goto done; // Try and send last buffered sample
83+
84+
do {
85+
if (buffPtr == buffLen) {
86+
int ret = op_read_stereo(of, (opus_int16 *)buff, OPUS_BUFF);
87+
if (ret == OP_HOLE) {
88+
// fprintf(stderr,"\nHole detected! Corrupt file segment?\n");
89+
continue;
90+
} else if (ret < 0) {
91+
running = false;
92+
goto done;
93+
}
94+
buffPtr = 0;
95+
buffLen = ret * 2;
96+
}
97+
98+
lastSample[AudioOutput::LEFTCHANNEL] = buff[buffPtr] & 0xffff;
99+
lastSample[AudioOutput::RIGHTCHANNEL] = buff[buffPtr+1] & 0xffff;
100+
buffPtr += 2;
101+
} while (running && output->ConsumeSample(lastSample));
102+
103+
done:
104+
file->loop();
105+
output->loop();
106+
107+
return running;
108+
}
109+
110+
bool AudioGeneratorTonie::stop()
111+
{
112+
if (of) op_free(of);
113+
of = nullptr;
114+
free(buff);
115+
buff = nullptr;
116+
running = false;
117+
output->stop();
118+
return true;
119+
}
120+
121+
bool AudioGeneratorTonie::isRunning()
122+
{
123+
return running;
124+
}
125+
126+
127+
int AudioGeneratorTonie::read_cb(unsigned char *_ptr, int _nbytes) {
128+
if (_nbytes == 0) return 0;
129+
_nbytes = file->read(_ptr, _nbytes);
130+
if (_nbytes == 0) return -1;
131+
return _nbytes;
132+
}
133+
134+
int AudioGeneratorTonie::seek_cb(opus_int64 _offset, int _whence) {
135+
if (!file->seek((int32_t)_offset, _whence)) return -1;
136+
return 0;
137+
}
138+
139+
opus_int64 AudioGeneratorTonie::tell_cb() {
140+
return file->getPos();
141+
}
142+
143+
int AudioGeneratorTonie::close_cb() {
144+
// NO OP, we close in main loop
145+
return 0;
146+
}

AudioGeneratorTonie.h

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
AudioGeneratorTonie
3+
Audio output generator that plays Opus audio files
4+
5+
Copyright (C) 2020 Earle F. Philhower, III
6+
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation, either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#ifndef _AUDIOGENERATORTONIE_H
22+
#define _AUDIOGENERATORTONIE_H
23+
24+
#include <AudioGenerator.h>
25+
//#include "libopus/opus.h"
26+
#include "opusfile/opusfile.h"
27+
28+
class AudioGeneratorTonie : public AudioGenerator
29+
{
30+
public:
31+
AudioGeneratorTonie();
32+
virtual ~AudioGeneratorTonie() override;
33+
virtual bool begin(AudioFileSource *source, AudioOutput *output) override;
34+
virtual bool loop() override;
35+
virtual bool stop() override;
36+
virtual bool isRunning() override;
37+
38+
protected:
39+
// Opus callbacks, need static functions to bounce into C++ from C
40+
static int OPUS_read(void *_stream, unsigned char *_ptr, int _nbytes) {
41+
return static_cast<AudioGeneratorTonie*>(_stream)->read_cb(_ptr, _nbytes);
42+
}
43+
static int OPUS_seek(void *_stream, opus_int64 _offset, int _whence) {
44+
return static_cast<AudioGeneratorTonie*>(_stream)->seek_cb(_offset, _whence);
45+
}
46+
static opus_int64 OPUS_tell(void *_stream) {
47+
return static_cast<AudioGeneratorTonie*>(_stream)->tell_cb();
48+
}
49+
static int OPUS_close(void *_stream) {
50+
return static_cast<AudioGeneratorTonie*>(_stream)->close_cb();
51+
}
52+
53+
// Actual Opus callbacks
54+
int read_cb(unsigned char *_ptr, int _nbytes);
55+
int seek_cb(opus_int64 _offset, int _whence);
56+
opus_int64 tell_cb();
57+
int close_cb();
58+
59+
private:
60+
OpusFileCallbacks cb = {OPUS_read, OPUS_seek, OPUS_tell, OPUS_close};
61+
OggOpusFile *of;
62+
int prev_li; // To detect changes in streams
63+
64+
int16_t *buff;
65+
uint32_t buffPtr;
66+
uint32_t buffLen;
67+
};
68+
69+
#endif
70+

0 commit comments

Comments
 (0)