Compare commits

...

2 Commits

Author SHA1 Message Date
3e5da27250 Implemented Buzzer 2024-11-22 21:01:23 -05:00
a7afcd2551 Now using SDL2 2.30.9 2024-11-22 00:09:54 -05:00
7 changed files with 132 additions and 1 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "submodules/sdl2"]
path = submodules/sdl2
url = https://github.com/libsdl-org/SDL

71
Buzzer.cpp Normal file
View 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
View 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
View 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)

View File

@@ -1,3 +1,3 @@
## choco-chip8 ## choco-chip8
CHIP-8 interpreter written in C++, using ncurses for display. CHIP-8 interpreter written in C++, using SDL2 for display.

23
main.cpp Normal file
View 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;
}

1
submodules/sdl2 Submodule

Submodule submodules/sdl2 added at c98c4fbff6