-
Notifications
You must be signed in to change notification settings - Fork 0
/
AudioOutput.cpp
125 lines (103 loc) · 3.67 KB
/
AudioOutput.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
#include <cstdio>
#include <iostream>
#include "AudioOutput.h"
#define printErr(em) printf("PortAudio error: %s\n", Pa_GetErrorText(em))
AudioOutput::AudioOutput() {
auto err = Pa_Initialize();
if( err != paNoError ) {
printErr(err);
}
}
int AudioOutput::initialize(deviceSettings settings) {
int framesPerBuffer;
if(settings.bufferSize==0){
framesPerBuffer = paFramesPerBufferUnspecified;
}else {
framesPerBuffer = 1000 / settings.bufferSize;
}
devSettings = settings;
/* Open an audio I/O stream. */
auto err = Pa_OpenDefaultStream( &stream,
0, /* no input channels */
1, /* stereo output FOR NOW */
paFloat32, /* 32 bit floating point output */
devSettings.sampleRate,
framesPerBuffer, /* frames per buffer, i.e. the number
of sample frames that PortAudio will
request from the callback. Many apps
may want to use
paFramesPerBufferUnspecified, which
tells PortAudio to pick the best,
possibly changing, buffer size.*/
callback, /* this is your callback function */
this ); /*This is a pointer that will be passed to
your callback*/
if( err != paNoError ) {printErr(err); return err;}
return 0;
}
int AudioOutput::terminate() {
auto err = Pa_IsStreamStopped(stream);
//if not stopped: stop it
if(err == 0) {
auto err = Pa_CloseStream(stream);
if (err != paNoError) {
printErr(err);
return err;
}
}
err = Pa_Terminate();
if( err != paNoError ) {
printErr(err);
return err;
}
return 0;
}
unsigned long int counter = 0;
int AudioOutput::callback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData ) {
auto *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer; /* Prevent unused variable warning. */
auto *audioOutput = (AudioOutput*)userData;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = audioOutput->generator->output((counter+i)*(1000/audioOutput->devSettings.sampleRate));
}
counter += framesPerBuffer;
return 0;
}
int AudioOutput::startStream() {
//TODO: Assert callback function is set
auto err = Pa_StartStream(stream);
if(err!= paNoError){printErr(err); return 1;}
return 0;
}
int AudioOutput::stopStream() {
auto err = Pa_StopStream(stream);
if(err!= paNoError){printErr(err); return 1;}
return 0;
}
int AudioOutput::deviceCount() {
int numDevices;
numDevices = Pa_GetDeviceCount();
if(numDevices<0){
printErr(numDevices);
return 0;
}
return numDevices;
}
std::optional<const PaDeviceInfo*> AudioOutput::getDeviceInfo(int i) {
auto n = deviceCount();
if(i<0 || i>n){return std::nullopt;}
return Pa_GetDeviceInfo(i);
}
int AudioOutput::printDevices() {
auto n = deviceCount();
for(int i = 0; i<n; i++){
std::cout << getDeviceInfo(i).value()->name << std::endl;
}
return 0;
}