-
Notifications
You must be signed in to change notification settings - Fork 0
/
loopback.cpp
120 lines (93 loc) · 4.23 KB
/
loopback.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
#include "SdlGuard.h"
#define SDL_MAIN_HANDLED
#include "SDL2/SDL.h"
#include <cstdlib>
#include <iostream>
#include <stdexcept>
namespace consts {
static const int audioSpecFrequency = 48000;
static const SDL_AudioFormat audioSpecFormat = AUDIO_F32SYS;
static const uint8_t audioSpecChannels = 1;
static const uint8_t audioSpecSilence = 0;
static const uint16_t audioSpecSamples = 4096;
static const uint16_t audioSpecPadding = 0;
static const uint32_t audioSpecSize = 0;
static const int allowedAudioChange = 0;
static const int pauseDisable = 0;
static const uint32_t recordLengthMsec = 5000;
} // namespace consts
bool isValid(SDL_AudioDeviceID deviceId)
{
return (deviceId >= 2); // see SDL_OpenAudioDevice()
}
void printAudioDevices(int isCapture)
{
const int numAudioDevices = SDL_GetNumAudioDevices(isCapture);
std::cout << "Available audio " << (isCapture ? "capture" : "playback") << " devices:\n";
for(int i = 0; i < numAudioDevices; ++i)
std::cout << SDL_GetAudioDeviceName(i, isCapture) << "\n";
std::cout << "\n";
}
SDL_AudioDeviceID setupPlayDevice()
{
static const int isCapture = SDL_FALSE;
printAudioDevices(isCapture);
const SDL_AudioSpec want = {
consts::audioSpecFrequency, /**< DSP frequency -- samples per second */
consts::audioSpecFormat, /**< Audio data format */
consts::audioSpecChannels, /**< Number of channels: 1 mono, 2 stereo */
consts::audioSpecSilence, /**< Audio buffer silence value (calculated) */
consts::audioSpecSamples, /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
consts::audioSpecPadding, /**< Necessary for some compile environments */
consts::audioSpecSize, /**< Audio buffer size in bytes (calculated) */
nullptr, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
nullptr /**< Userdata passed to callback (ignored for NULL callbacks). */
};
SDL_AudioSpec have;
const auto deviceId = SDL_OpenAudioDevice(nullptr, isCapture, &want, &have, consts::allowedAudioChange);
if(!isValid(deviceId))
throw std::runtime_error(std::string("Failed to open audio: ") + SDL_GetError());
return deviceId;
}
void captureCallback(void* userdata, uint8_t* stream, int len)
{
auto playDeviceId = *reinterpret_cast<const SDL_AudioDeviceID*>(userdata);
if(SDL_QueueAudio(playDeviceId, stream, static_cast<uint32_t>(len)))
throw std::runtime_error(std::string("Failed to queue audio: ") + SDL_GetError());
}
SDL_AudioDeviceID setupCaptureDevice(SDL_AudioDeviceID* playDeviceId)
{
static const int isCapture = SDL_TRUE;
printAudioDevices(isCapture);
const SDL_AudioSpec want = {
consts::audioSpecFrequency, /**< DSP frequency -- samples per second */
consts::audioSpecFormat, /**< Audio data format */
consts::audioSpecChannels, /**< Number of channels: 1 mono, 2 stereo */
consts::audioSpecSilence, /**< Audio buffer silence value (calculated) */
consts::audioSpecSamples, /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
consts::audioSpecPadding, /**< Necessary for some compile environments */
consts::audioSpecSize, /**< Audio buffer size in bytes (calculated) */
captureCallback, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
playDeviceId /**< Userdata passed to callback (ignored for NULL callbacks). */
};
SDL_AudioSpec have;
const auto deviceId = SDL_OpenAudioDevice(nullptr, isCapture, &want, &have, consts::allowedAudioChange);
if(!isValid(deviceId))
throw std::runtime_error(std::string("Failed to open audio: ") + SDL_GetError());
return deviceId;
}
int main(int, char**)
try {
audio::SdlGuard SdlGuard;
auto playDeviceId = setupPlayDevice();
const auto captureDeviceId = setupCaptureDevice(&playDeviceId);
SDL_PauseAudioDevice(playDeviceId, consts::pauseDisable);
SDL_PauseAudioDevice(captureDeviceId, consts::pauseDisable);
SDL_Delay(consts::recordLengthMsec);
SDL_CloseAudioDevice(captureDeviceId);
SDL_CloseAudioDevice(playDeviceId);
return EXIT_SUCCESS;
} catch(const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}