Skip to content

Instantly share code, notes, and snippets.

@niuniulla
Last active March 29, 2024 22:33
Show Gist options
  • Save niuniulla/8e21c590525fe0727f6067dd625191b3 to your computer and use it in GitHub Desktop.
Save niuniulla/8e21c590525fe0727f6067dd625191b3 to your computer and use it in GitHub Desktop.
A minimal implementation of audio recording and playback using SDL2.
/*
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages arising
from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
/*
A minimal implementation of audio recording and playback using SDL2.
*/
#include <SDL2/SDL.h>
#include <stdlib.h>
#include <iostream>
static Uint8* buffer = 0;
static int recordPos = 0; // buffer position for recording
static int playbackPos = 0; // buffer position for playback
int gLenghtOfRecordingSecond = 5; // in seconds, length of recording and playback
// callback function for recording
void recordCallback(void *userdata, Uint8 *stream, int len) {
SDL_memcpy(buffer + recordPos, stream, len); // copy data from stream to buffer
recordPos += len;
}
// callback function for playback
void playbackCallback(void *userdata, Uint8 *stream, int len) {
SDL_memcpy(stream, buffer + playbackPos, len); // copy data from buffer to stream
playbackPos += len;
}
// main function
int main() {
// init SDL, under circumstance of this application
SDL_Init(SDL_INIT_AUDIO);
//Get capture device count
int deviceCount = SDL_GetNumAudioDevices(SDL_TRUE);
// There should have at least 1 device to work
if (deviceCount < 1)
{
std::cout << "ERR - There is no valid audio devices. SDL error: " << SDL_GetError() << std::endl;
return 1;
}
std::cout << "INFO - There are: " << deviceCount << " recording devices available." << std::endl;
// get device names
for (int i=0; i<deviceCount; i++)
{
std::cout << "INFO - Device" << i << ": " << SDL_GetAudioDeviceName(i, SDL_TRUE) << std::endl;
}
// select audio device
SDL_AudioDeviceID recordingDeviceId = 0;
SDL_AudioDeviceID playbackDeviceId = 0;
//Default recording spec
SDL_AudioSpec desiredRecordingSpec, receivedRecordingSpec;
SDL_zero(desiredRecordingSpec);
desiredRecordingSpec.freq = 44100;
desiredRecordingSpec.format = AUDIO_F32;
desiredRecordingSpec.channels = 2;
desiredRecordingSpec.samples = 4096;
desiredRecordingSpec.callback = recordCallback;
//Open recording device
int index = deviceCount - 1; // can be any number as long as it is smaller than the available devices
recordingDeviceId = SDL_OpenAudioDevice( SDL_GetAudioDeviceName( index, SDL_TRUE ), SDL_TRUE, &desiredRecordingSpec, &receivedRecordingSpec, SDL_AUDIO_ALLOW_FORMAT_CHANGE );
if( recordingDeviceId == 0 )
{
std::cout << "ERR - Failed to open recording device. SDL error :" << SDL_GetError() << std::endl;
return -1;
}
// default playing spec
SDL_AudioSpec desiredPlaybackSpec, receivedPlaybackSpec;
SDL_zero(desiredPlaybackSpec);
desiredPlaybackSpec.freq = 44100;
desiredPlaybackSpec.format = AUDIO_F32;
desiredPlaybackSpec.channels = 2;
desiredPlaybackSpec.samples = 4096;
desiredPlaybackSpec.callback = playbackCallback;
//open playback device
playbackDeviceId = SDL_OpenAudioDevice(NULL, SDL_FALSE, &desiredPlaybackSpec, &receivedPlaybackSpec, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (playbackDeviceId == 0)
{
std::cout << "ERR - Failed to open playback device. SDL error: " << SDL_GetError() << std::endl;
return -1;
}
// compute the buffer size for recording
// compute bytes per sample = channels * audio bit format / 8
int bytePerSample = receivedRecordingSpec.channels * (SDL_AUDIO_BITSIZE(receivedRecordingSpec.format) / 8);
// compute bytes per second = freq * bytes/sample
int bytePerSecond = bytePerSample * receivedRecordingSpec.freq;
// compte total bytes for buffer
int bufferSize = bytePerSecond * gLenghtOfRecordingSecond;
// allocate memory for buffer
buffer = new Uint8[bufferSize];
// init buffer
memset(buffer, 0, bufferSize);
std::cout << "INFO - Allocated :" << bufferSize << " bytes for buffer." << std::endl;
// recording
std::cout << "INFO - Start to record..." << std::endl;
// unpause device to make it work, it is paused by default
SDL_PauseAudioDevice(recordingDeviceId, SDL_FALSE);
// I did a sleep here to wait for the recording to finish
SDL_Delay(5050);
// pause recording
SDL_PauseAudioDevice(recordingDeviceId, SDL_TRUE);
std::cout << "INFO - Playing back the recorded..." << std::endl;
// unpause device to playback
SDL_PauseAudioDevice(playbackDeviceId, SDL_FALSE);
// delay to finish playback
SDL_Delay(6000);
// cleaning
if (!buffer)
{
delete[] buffer;
buffer = nullptr;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment