windows checkpoint
This commit is contained in:
68
scripts/build.bat
Normal file
68
scripts/build.bat
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
REM ================================
|
||||||
|
REM Configuration
|
||||||
|
REM ================================
|
||||||
|
|
||||||
|
set BUILD_DIR=build
|
||||||
|
set CONFIG=Release
|
||||||
|
|
||||||
|
REM Update these paths if needed
|
||||||
|
set QT_ROOT=C:\Qt\6.6.1\msvc2022_64
|
||||||
|
set RTAUDIO_ROOT=C:\rtaudio
|
||||||
|
|
||||||
|
REM ================================
|
||||||
|
REM Environment setup
|
||||||
|
REM ================================
|
||||||
|
|
||||||
|
call "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||||
|
|
||||||
|
set PATH=%QT_ROOT%\bin;%PATH%
|
||||||
|
|
||||||
|
REM ================================
|
||||||
|
REM Configure
|
||||||
|
REM ================================
|
||||||
|
|
||||||
|
if not exist %BUILD_DIR% (
|
||||||
|
mkdir %BUILD_DIR%
|
||||||
|
)
|
||||||
|
|
||||||
|
cmake -S . -B %BUILD_DIR% ^
|
||||||
|
-G Ninja ^
|
||||||
|
-DCMAKE_BUILD_TYPE=%CONFIG% ^
|
||||||
|
-DCMAKE_PREFIX_PATH=%QT_ROOT% ^
|
||||||
|
-DRTAUDIO_ROOT=%RTAUDIO_ROOT%
|
||||||
|
|
||||||
|
if errorlevel 1 goto error
|
||||||
|
|
||||||
|
REM ================================
|
||||||
|
REM Build
|
||||||
|
REM ================================
|
||||||
|
|
||||||
|
cmake --build %BUILD_DIR%
|
||||||
|
|
||||||
|
if errorlevel 1 goto error
|
||||||
|
|
||||||
|
REM ================================
|
||||||
|
REM Deploy Qt + RtAudio
|
||||||
|
REM ================================
|
||||||
|
|
||||||
|
cd %BUILD_DIR%
|
||||||
|
|
||||||
|
windeployqt MyQtApp.exe
|
||||||
|
|
||||||
|
copy "%RTAUDIO_ROOT%\bin\rtaudio.dll" .
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Build successful.
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
echo.
|
||||||
|
echo Build FAILED.
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:end
|
||||||
|
endlocal
|
||||||
|
pause
|
||||||
73
src/synth/AudioEngine.cpp
Normal file
73
src/synth/AudioEngine.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
#include "AudioEngine.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
AudioEngine::AudioEngine() {
|
||||||
|
if(audio_.getDeviceCount() < 1) {
|
||||||
|
throw std::runtime_error("No audio devices found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioEngine::~AudioEngine() {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioEngine::start() {
|
||||||
|
|
||||||
|
RtAudio::StreamParameters params;
|
||||||
|
params.deviceId = audio_.getDefaultOutputDevice();
|
||||||
|
params.nChannels = 1;
|
||||||
|
params.firstChannel = 0;
|
||||||
|
|
||||||
|
RtAudio::StreamOptions options;
|
||||||
|
options.flags = RTAUDIO_MINIMIZE_LATENCY;
|
||||||
|
|
||||||
|
try {
|
||||||
|
audio_.openStream(¶ms, nullptr, RTAUDIO_FLOAT32, sampleRate_, &bufferFrames_, &AudioEngine::audioCallback, this, &options);
|
||||||
|
audio_.startStream();
|
||||||
|
} catch(RtAudioError& e) {
|
||||||
|
std::cerr << e.getMessage() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "sample rate: " << sampleRate_ << " buffer frames: " << bufferFrames_ << std::endl;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioEngine::stop() {
|
||||||
|
|
||||||
|
if(audio_.isStreamRunning()) audio_.stopStream();
|
||||||
|
if(audio_.isStreamOpen()) audio_.closeStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioEngine::setFrequency(float freq) {
|
||||||
|
targetFreq_.store(freq, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t AudioEngine::audioCallback( void* outputBuffer, void*, uint32_t nFrames, double, RtAudioStreamStatus status, void* userData) {
|
||||||
|
|
||||||
|
if (status) std::cerr << "Stream underflow!" << std::endl;
|
||||||
|
|
||||||
|
return static_cast<AudioEngine*>(userData)->process(static_cast<float*>(outputBuffer), nFrames);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t AudioEngine::process(float* out, uint32_t nFrames) {
|
||||||
|
const float sr = static_cast<float>(sampleRate_);
|
||||||
|
float target = targetFreq_.load(std::memory_order_relaxed);
|
||||||
|
float freqStep = (target - currentFreq_) / nFrames;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nFrames; ++i) {
|
||||||
|
currentFreq_ += freqStep;
|
||||||
|
|
||||||
|
float phaseInc = 2.0f * M_PI * currentFreq_ / sr;
|
||||||
|
out[i] = std::sin(phase_);
|
||||||
|
|
||||||
|
phase_ += phaseInc;
|
||||||
|
if (phase_ > 2.0f * M_PI) phase_ -= 2.0f * M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
31
src/synth/AudioEngine.h
Normal file
31
src/synth/AudioEngine.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <RtAudio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
class AudioEngine {
|
||||||
|
|
||||||
|
public:
|
||||||
|
AudioEngine();
|
||||||
|
~AudioEngine();
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
void setFrequency(float freq);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int32_t audioCallback(void* outputBuffer, void* inputBuffer, uint32_t nFrames, double streamTime, RtAudioStreamStatus status, void* userData);
|
||||||
|
int32_t process(float* out, uint32_t nFrames);
|
||||||
|
|
||||||
|
RtAudio audio_;
|
||||||
|
uint32_t sampleRate_ = 44100;
|
||||||
|
uint32_t bufferFrames_ = 256;
|
||||||
|
|
||||||
|
std::atomic<float> targetFreq_{ 400.0f };
|
||||||
|
float currentFreq_ = 440.0f;
|
||||||
|
float phase_ = 0.0f;
|
||||||
|
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user