-
Notifications
You must be signed in to change notification settings - Fork 1
/
AelPlayer.cpp
158 lines (119 loc) · 4.57 KB
/
AelPlayer.cpp
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "AelPlayer.h"
namespace Ael{
//////////////////////////////////////////////////////////////////
//Classe AelPlayer
//////////////////////////////////////////////////////////////////
/****************************************************************************
*Função tick
*Parâmetros: void*, void*, unsigned int, double, RtAudioStreamStatus, void*
*Função callback utilizada pela RTAudio
****************************************************************************/
int tick(void* outputBuffer, void* inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* dataPointer){
Ael::AelPlayer* player = reinterpret_cast<AelPlayer*>(dataPointer);
int* out = reinterpret_cast<int*>(outputBuffer);
player->threadptr->join(); //retorna quando thread termina
memcpy(outputBuffer, player->frames, player->bufferFrames * player->channels * sizeof(int)); //copia novo buffer com novas amostras
delete player->threadptr; player->threadptr = NULL; //destroi thread em execução
player->threadptr = new thread(player->tick, player); //inicia uma nova thread
/*if (player->status == PLAYING) return 0;
else if (player->status == PAUSED) return 1;
else return 2;
*/
return 0;
}
/****************************************************************************
*Construtor da AelPlayer
*Parâmetros: int, float, int
****************************************************************************/
AelPlayer::AelPlayer(int n_channels, float samplerate, int bufferFrames) : mixerptr(new AelMixer), threadptr(NULL), frames(new int[bufferFrames * 2]), sampleRate(samplerate), channels(n_channels),status(STOPPED), bufferFrames(bufferFrames){
}
/****************************************************************************
*Função membro openStream (utility function)
*Parâmetros: void
*Abre a stream para reprodução com parâmetros pretendidos
****************************************************************************/
void AelPlayer::openStream(){
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = channels;
RtAudioFormat format = RTAUDIO_SINT32;
try{
dac.openStream(¶meters, NULL, format, (unsigned int)sampleRate, (unsigned int*)&bufferFrames, Ael::tick, (void*) this);
}
catch (RtAudioError &error){
error.printMessage();
}
}
/****************************************************************************
*Função membro start
*Parâmetros: void
*Inicia/retoma reprodução de audio
****************************************************************************/
void AelPlayer::start(){
//static int firstTimePlaying = 1;
if (status == STOPPED){
threadptr = new thread(this->tick, this);
openStream();
}
try{
dac.startStream();
status = PLAYING;
}
catch (RtAudioError &error){
error.printMessage();
}
}
/****************************************************************************
*Função membro pause
*Parâmetros: void
*Suspende reprodução de áudio
****************************************************************************/
void AelPlayer::pause(){
if(status != PLAYING)
return;
try{
if (dac.isStreamOpen())
dac.stopStream();
status = PAUSED;
}
catch (RtAudioError &error){
error.printMessage();
}
}
/****************************************************************************
*Função membro top
*Parâmetros: void
*Termina reprodução de áudio
****************************************************************************/
void AelPlayer::stop(){
if(status != STOPPED)
dac.closeStream();
if(threadptr != NULL){
if(threadptr->joinable())
threadptr->join();
delete threadptr;
}
mixerptr->setPosFrames(0);
status = STOPPED;
}
/****************************************************************************
*Função membro tick
*Parâmetros: void
*Preenche buffer da classe com amostras da mixer
****************************************************************************/
void AelPlayer::tick(AelPlayer* player){
int* initframes = player->frames;
for (unsigned int i = 0; i < player->bufferFrames; i++){
Ael::AelFrame aux = player->mixerptr->getNextFrame();
for (int j = 0; j < player->channels; j++){
*initframes++ = aux[j];
}
}
}
AelPlayer::~AelPlayer(){
delete [] frames;
delete mixerptr;
//delete threadptr;
dac.closeStream();
}
}