Implemented Buzzer
This commit is contained in:
71
Buzzer.cpp
Normal file
71
Buzzer.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "Buzzer.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
void SDLCALL Buzzer::audioCallback(void *userdata, Uint8 *stream, int len) {
|
||||||
|
static_cast<Buzzer*>(userdata)->copySamples(stream, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
Buzzer::Buzzer(unsigned buzzerFrequency) {
|
||||||
|
SDL_AudioSpec desired;
|
||||||
|
SDL_AudioSpec obtained;
|
||||||
|
|
||||||
|
SDL_zero(desired);
|
||||||
|
desired.channels = 1;
|
||||||
|
desired.freq = 44000;
|
||||||
|
desired.format = AUDIO_S16SYS;
|
||||||
|
desired.samples = 4096;
|
||||||
|
desired.callback = audioCallback;
|
||||||
|
desired.userdata = this;
|
||||||
|
|
||||||
|
mAudioDevice = SDL_OpenAudioDevice(NULL, SDL_FALSE, &desired, &obtained, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
|
||||||
|
if(mAudioDevice == 0) {
|
||||||
|
throw std::runtime_error(SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// period of the sine wave, in samples, to obtained the desired
|
||||||
|
// buffer buzzer frequency at a particular audio sample rate
|
||||||
|
double waveLength = double(obtained.freq) / buzzerFrequency;
|
||||||
|
// buffer size that fits a whole number of sine waves and is roughly the same size of obtained.samples
|
||||||
|
size_t numSamples = waveLength * std::max(std::floor(obtained.samples / waveLength), 1.0);
|
||||||
|
mSamples.resize(numSamples);
|
||||||
|
|
||||||
|
// generate the sine wave
|
||||||
|
auto amplitude = std::numeric_limits<sample_t>::max();
|
||||||
|
auto angularFreq = 2.0 * M_PI / waveLength;
|
||||||
|
for(size_t iSample = 0; iSample < numSamples; iSample++) {
|
||||||
|
mSamples[iSample] = amplitude * std::sin(angularFreq * iSample);
|
||||||
|
}
|
||||||
|
miCurrentSample = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buzzer::~Buzzer() {
|
||||||
|
SDL_CloseAudioDevice(mAudioDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buzzer::on() {
|
||||||
|
SDL_PauseAudioDevice(mAudioDevice, SDL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buzzer::off() {
|
||||||
|
SDL_PauseAudioDevice(mAudioDevice, SDL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buzzer::copySamples(Uint8 *stream, int len) {
|
||||||
|
// Copy len samples from the current position of the buffer,
|
||||||
|
// looping back to the start of the buffer when needed.
|
||||||
|
while(len > 0) {
|
||||||
|
size_t numBytes = std::min(sizeof(sample_t) * (mSamples.size() - miCurrentSample), size_t(len));
|
||||||
|
size_t numSamples = numBytes / sizeof(sample_t);
|
||||||
|
std::memcpy(stream, mSamples.data() + miCurrentSample, numBytes);
|
||||||
|
stream += numBytes;
|
||||||
|
len -= numBytes;
|
||||||
|
miCurrentSample += numSamples;
|
||||||
|
if(miCurrentSample >= mSamples.size()) {
|
||||||
|
miCurrentSample = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Buzzer.hpp
Normal file
24
Buzzer.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <SDL2/SDL_audio.h>
|
||||||
|
|
||||||
|
class Buzzer {
|
||||||
|
public:
|
||||||
|
using sample_t = Sint16;
|
||||||
|
|
||||||
|
Buzzer(unsigned frequency);
|
||||||
|
~Buzzer();
|
||||||
|
|
||||||
|
void on();
|
||||||
|
void off();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len);
|
||||||
|
void copySamples(Uint8 *stream, int len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<sample_t> mSamples;
|
||||||
|
SDL_AudioDeviceID mAudioDevice;
|
||||||
|
size_t miCurrentSample;
|
||||||
|
};
|
||||||
9
CMakeLists.txt
Normal file
9
CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(chocochip8)
|
||||||
|
SET(CMAKE_BUILD_TYPE Debug)
|
||||||
|
|
||||||
|
add_subdirectory(submodules/sdl2)
|
||||||
|
|
||||||
|
SET(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
add_executable(chocochip8 main.cpp Buzzer.cpp)
|
||||||
|
target_link_libraries(chocochip8 SDL2::SDL2-static)
|
||||||
23
main.cpp
Normal file
23
main.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#include "Buzzer.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char* args[]) {
|
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
||||||
|
std::cerr << "Couldn't initialize SDL: " << SDL_GetError() << '\n';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buzzer buzzer(440);
|
||||||
|
buzzer.on();
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
while(SDL_WaitEvent(&event) && event.type != SDL_QUIT) {
|
||||||
|
}
|
||||||
|
|
||||||
|
buzzer.off();
|
||||||
|
SDL_Quit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user