Skip to content

Commit

Permalink
renames and cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
mporsch committed Sep 25, 2021
1 parent 0173f67 commit 703856f
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 140 deletions.
42 changes: 24 additions & 18 deletions AudioDevice.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef AUDIO_DEVICE_H
#define AUDIO_DEVICE_H

#include "AudioGuard.h"
#include "SdlGuard.h"

#define SDL_MAIN_HANDLED
#include "SDL2/SDL.h"
Expand All @@ -11,12 +11,19 @@
#include <list>
#include <vector>

namespace audio {

struct Metadata
{
int sampleRate = 48000; // sampling frequency [Hz]
uint8_t channelCount = 1; // number of channels to record in parallel (i.e. mono/stereo)
uint16_t sampleCount = 4096; // number of samples to capture in one group
};

template<typename T>
struct Sequence
{
int sampleRate;
uint8_t channelCount;
uint16_t sampleSize;
Metadata metadata;
std::list<std::vector<T>> storage;

void push(const uint8_t* stream, int len);
Expand All @@ -32,45 +39,44 @@ struct Sequence
};

template<typename T>
struct AudioDeviceCapture
struct DeviceCapture
{
AudioDeviceCapture(int sampleRate,
uint8_t channelCount,
uint16_t sampleSize);
AudioDeviceCapture(const AudioDeviceCapture&) = delete;
AudioDeviceCapture(AudioDeviceCapture&&) = delete;
DeviceCapture(const Metadata& metadata = Metadata());
DeviceCapture(const DeviceCapture&) = delete;
DeviceCapture(DeviceCapture&&) = delete;

Sequence<T> record(std::chrono::milliseconds length);
Sequence<T> record(uint32_t lengthMsec);

static void deviceCallback(void* userdata, uint8_t* stream, int len);
void deviceCallback(uint8_t* stream, int len);

private:
AudioGuard guard_;
SdlGuard guard_;
Sequence<T> seq_;
SDL_AudioDeviceID deviceId_;
};

template<typename T>
struct AudioDevicePlayback
struct DevicePlayback
{
AudioDevicePlayback(int sampleRate,
uint8_t channelCount,
uint16_t sampleSize);
AudioDevicePlayback(const AudioDevicePlayback&) = delete;
AudioDevicePlayback(AudioDevicePlayback&&) = delete;
DevicePlayback(const Metadata& metadata = Metadata());
DevicePlayback(const DevicePlayback&) = delete;
DevicePlayback(DevicePlayback&&) = delete;

void play(Sequence<T> seq);

static void deviceCallback(void* userdata, uint8_t* stream, int len);
void deviceCallback(uint8_t* stream, int len);

private:
AudioGuard guard_;
SdlGuard guard_;
SDL_AudioDeviceID deviceId_;
Sequence<T> seq_;
};

} // namespace audio

#include "AudioDevice_impl.h"

#endif // AUDIO_DEVICE_H
66 changes: 36 additions & 30 deletions AudioDevice_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <iostream>
#include <stdexcept>

namespace audio {

namespace detail {
static const uint8_t audioSpecSilence = 0;
static const uint16_t audioSpecPadding = 0;
Expand All @@ -35,7 +37,7 @@ namespace detail {
return (deviceId >= 2); // see SDL_OpenAudioDevice()
}

inline void printAudioDevices(int isCapture)
inline void printDevices(int isCapture)
{
const int numAudioDevices = SDL_GetNumAudioDevices(isCapture);

Expand Down Expand Up @@ -80,36 +82,33 @@ std::vector<T> Sequence<T>::pop()
return ret;
}


template<typename T>
std::chrono::milliseconds Sequence<T>::length() const
{
assert(sampleRate > 0);
return std::chrono::milliseconds((storage.size() * sampleSize) / (sampleRate / 1000));
assert(metadata.sampleRate > 0);
return std::chrono::milliseconds((storage.size() * metadata.sampleCount) / (metadata.sampleRate / 1000));
}


template<typename T>
AudioDeviceCapture<T>::AudioDeviceCapture(int sampleRate,
uint8_t channelCount,
uint16_t sampleSize)
: seq_{sampleRate, channelCount, sampleSize, {}}
DeviceCapture<T>::DeviceCapture(const Metadata& metadata)
: seq_{metadata, {}}
{
const SDL_AudioSpec want = {
sampleRate, /**< DSP frequency -- samples per second */
metadata.sampleRate, /**< DSP frequency -- samples per second */
detail::FormatLookUp<T>::format, /**< Audio data format */
channelCount, /**< Number of channels: 1 mono, 2 stereo */
metadata.channelCount, /**< Number of channels: 1 mono, 2 stereo */
detail::audioSpecSilence, /**< Audio buffer silence value (calculated) */
sampleSize, /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
metadata.sampleCount, /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
detail::audioSpecPadding, /**< Necessary for some compile environments */
detail::audioSpecSize, /**< Audio buffer size in bytes (calculated) */
AudioDeviceCapture<T>::deviceCallback, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
DeviceCapture<T>::deviceCallback, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
this /**< Userdata passed to callback (ignored for NULL callbacks). */
};

static const int isCapture = SDL_TRUE;

detail::printAudioDevices(isCapture);
detail::printDevices(isCapture);

SDL_AudioSpec have;
deviceId_ = SDL_OpenAudioDevice(nullptr, isCapture, &want, &have, detail::allowedAudioChange);
Expand All @@ -118,7 +117,14 @@ AudioDeviceCapture<T>::AudioDeviceCapture(int sampleRate,
}

template<typename T>
Sequence<T> AudioDeviceCapture<T>::record(uint32_t lengthMsec)
Sequence<T> DeviceCapture<T>::record(std::chrono::milliseconds length)
{
using Msec = std::chrono::duration<uint32_t, std::milli>;
return record(std::chrono::duration_cast<Msec>(length).count());
}

template<typename T>
Sequence<T> DeviceCapture<T>::record(uint32_t lengthMsec)
{
std::cout << "recording for " << lengthMsec << "ms ..." << std::endl;

Expand All @@ -129,43 +135,41 @@ Sequence<T> AudioDeviceCapture<T>::record(uint32_t lengthMsec)

SDL_PauseAudioDevice(deviceId_, detail::pauseEnable);

return Sequence<T>{seq_.sampleRate, seq_.channelCount, seq_.sampleSize, std::move(seq_.storage)};
return Sequence<T>{seq_.metadata, std::move(seq_.storage)};
}

template<typename T>
void AudioDeviceCapture<T>::deviceCallback(void* userdata, uint8_t* stream, int len)
void DeviceCapture<T>::deviceCallback(void* userdata, uint8_t* stream, int len)
{
auto instance = reinterpret_cast<AudioDeviceCapture<T>*>(userdata);
auto instance = reinterpret_cast<DeviceCapture<T>*>(userdata);
instance->deviceCallback(stream, len);
}

template<typename T>
void AudioDeviceCapture<T>::deviceCallback(uint8_t* stream, int len)
void DeviceCapture<T>::deviceCallback(uint8_t* stream, int len)
{
seq_.push(stream, len);
}


template<typename T>
AudioDevicePlayback<T>::AudioDevicePlayback(int sampleRate,
uint8_t channelCount,
uint16_t sampleSize)
DevicePlayback<T>::DevicePlayback(const Metadata& metadata)
{
const SDL_AudioSpec want = {
sampleRate, /**< DSP frequency -- samples per second */
metadata.sampleRate, /**< DSP frequency -- samples per second */
detail::FormatLookUp<T>::format, /**< Audio data format */
channelCount, /**< Number of channels: 1 mono, 2 stereo */
metadata.channelCount, /**< Number of channels: 1 mono, 2 stereo */
detail::audioSpecSilence, /**< Audio buffer silence value (calculated) */
sampleSize, /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
metadata.sampleCount, /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
detail::audioSpecPadding, /**< Necessary for some compile environments */
detail::audioSpecSize, /**< Audio buffer size in bytes (calculated) */
AudioDevicePlayback<T>::deviceCallback, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
DevicePlayback<T>::deviceCallback, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
this /**< Userdata passed to callback (ignored for NULL callbacks). */
};

static const int isCapture = SDL_FALSE;

detail::printAudioDevices(isCapture);
detail::printDevices(isCapture);

SDL_AudioSpec have;
deviceId_ = SDL_OpenAudioDevice(nullptr, isCapture, &want, &have, detail::allowedAudioChange);
Expand All @@ -174,7 +178,7 @@ AudioDevicePlayback<T>::AudioDevicePlayback(int sampleRate,
}

template<typename T>
void AudioDevicePlayback<T>::play(Sequence<T> seq)
void DevicePlayback<T>::play(Sequence<T> seq)
{
seq_ = std::move(seq);

Expand All @@ -187,14 +191,14 @@ void AudioDevicePlayback<T>::play(Sequence<T> seq)
}

template<typename T>
void AudioDevicePlayback<T>::deviceCallback(void* userdata, uint8_t* stream, int len)
void DevicePlayback<T>::deviceCallback(void* userdata, uint8_t* stream, int len)
{
auto instance = reinterpret_cast<AudioDevicePlayback<T>*>(userdata);
auto instance = reinterpret_cast<DevicePlayback<T>*>(userdata);
instance->deviceCallback(stream, len);
}

template<typename T>
void AudioDevicePlayback<T>::deviceCallback(uint8_t* stream, int len)
void DevicePlayback<T>::deviceCallback(uint8_t* stream, int len)
{
auto samples = seq_.pop();
if (samples.empty()) {
Expand All @@ -211,4 +215,6 @@ void AudioDevicePlayback<T>::deviceCallback(uint8_t* stream, int len)
memset(stream + writeByteSize, 0, static_cast<size_t>(len) - writeByteSize);
}

} // namespace audio

#endif // AUDIO_DEVICE_IMPL_H
22 changes: 0 additions & 22 deletions AudioGuard.h

This file was deleted.

11 changes: 4 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,22 @@ project (audio-thingies CXX)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})

add_executable (echo echo.cpp AudioDevice.h AudioDevice_impl.h AudioGuard.cpp AudioGuard.h)
add_executable (echo echo.cpp AudioDevice.h AudioDevice_impl.h SdlGuard.cpp SdlGuard.h)
target_link_libraries(echo
#mingw32
${SDL2_LIBRARIES}
)

add_executable (loopback loopback.cpp AudioGuard.cpp AudioGuard.h)
add_executable (loopback loopback.cpp SdlGuard.cpp SdlGuard.h)
target_link_libraries(loopback
#mingw32
${SDL2_LIBRARIES}
)

add_executable (spectrum spectrum.cpp AudioDevice.h AudioDevice_impl.h AudioGuard.cpp AudioGuard.h)
add_executable (spectrum spectrum.cpp AudioDevice.h AudioDevice_impl.h SdlGuard.cpp SdlGuard.h)
target_link_libraries(spectrum
#mingw32
${SDL2_LIBRARIES}
)

add_executable (sweep sweep.cpp AudioDevice.h AudioDevice_impl.h AudioGuard.cpp AudioGuard.h)
add_executable (sweep sweep.cpp AudioDevice.h AudioDevice_impl.h SdlGuard.cpp SdlGuard.h)
target_link_libraries(sweep
${SDL2_LIBRARIES}
)
14 changes: 9 additions & 5 deletions AudioGuard.cpp → SdlGuard.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#include "AudioGuard.h"
#include "SdlGuard.h"

#define SDL_MAIN_HANDLED
#include "SDL2/SDL.h"

#include <stdexcept> // for std::runtime_error

unsigned int AudioGuard::m_instanceCount{};
std::mutex AudioGuard::m_mtx{};
namespace audio {

AudioGuard::AudioGuard()
unsigned int SdlGuard::m_instanceCount{};
std::mutex SdlGuard::m_mtx{};

SdlGuard::SdlGuard()
{
std::lock_guard<std::mutex> lock(m_mtx);

Expand All @@ -21,7 +23,7 @@ AudioGuard::AudioGuard()
++m_instanceCount;
}

AudioGuard::~AudioGuard()
SdlGuard::~SdlGuard()
{
std::lock_guard<std::mutex> lock(m_mtx);

Expand All @@ -31,3 +33,5 @@ AudioGuard::~AudioGuard()
SDL_Quit();
}
}

} // namespace audio
26 changes: 26 additions & 0 deletions SdlGuard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef SDL_AUDIO_GUARD_H
#define SDL_AUDIO_GUARD_H

#include <mutex> // for std::mutex

namespace audio {

class SdlGuard
{
public:
SdlGuard();
SdlGuard(SdlGuard const &other) = delete;
SdlGuard(SdlGuard &&other) = delete;
~SdlGuard();

SdlGuard &operator=(SdlGuard const &other) = delete;
SdlGuard &operator=(SdlGuard &&other) = delete;

private:
static unsigned int m_instanceCount;
static std::mutex m_mtx;
};

} // namespace audio

#endif // SDL_AUDIO_GUARD_H
8 changes: 2 additions & 6 deletions echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@
#include <iostream>

namespace consts {
static const int audioSpecFrequency = 48000;
static const uint8_t audioSpecChannels = 1;
static const uint16_t audioSpecSamples = 4096;

static const uint32_t recordLengthMsec = 5000;
} // namespace consts

int main(int, char**)
try {
AudioDeviceCapture<float> capture(consts::audioSpecFrequency, consts::audioSpecChannels, consts::audioSpecSamples);
audio::DeviceCapture<float> capture;
auto recording = capture.record(consts::recordLengthMsec);

AudioDevicePlayback<float> playback(consts::audioSpecFrequency, consts::audioSpecChannels, consts::audioSpecSamples);
audio::DevicePlayback<float> playback(recording.metadata);
playback.play(std::move(recording));

return EXIT_SUCCESS;
Expand Down
Loading

0 comments on commit 703856f

Please sign in to comment.