Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@
path = third_party/tclap
url = https://git.code.sf.net/p/tclap/code
branch = 1.4
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/google/benchmark
16 changes: 15 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.19)

project(Canvas)

option(CANVAS_BENCHMARK "Create benchmark executable" OFF)

set(CMAKE_CXX_STANDARD 14)

set(
Expand Down Expand Up @@ -79,5 +81,17 @@ else()
target_include_directories(canvas PRIVATE ${FFTW_INCLUDE_DIRS})
target_link_libraries(canvas PRIVATE ${FFTW_LIBRARIES})

target_link_libraries(canvas PRIVATE portaudio_static)
target_link_libraries(canvas PRIVATE portaudio_static)
endif()

if(CANVAS_BENCHMARK)
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
add_subdirectory(third_party/benchmark)
add_executable(
canvas_benchmark
src/benchmark/benchmark.cpp
src/Synth.hpp
src/Synth.cpp
)
target_link_libraries(canvas_benchmark benchmark::benchmark portaudio_static)
endif()
53 changes: 52 additions & 1 deletion src/Synth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@ Oscillator::Oscillator(float sampleRate, float frequency, float phase)
: m_sampleRate(sampleRate)
, m_frequency(frequency)
, m_phase(phase)
, m_phaseInc(m_frequency / m_sampleRate)
{
}

void Oscillator::processAdd(float* out1, float* out2, int blockSize) {
void Oscillator::processAddOriginal(float* out1, float* out2, int blockSize) {
for (int i = 0; i < blockSize; i++) {
m_phase = std::fmod(m_phase + m_frequency / m_sampleRate, 1.0);
float distortedPhase = std::fmod(distortPhase(m_phase, m_pdMode, m_pdDistort), 1.0);
Expand All @@ -93,6 +94,37 @@ void Oscillator::processAdd(float* out1, float* out2, int blockSize) {
m_amplitudeRight = m_targetAmplitudeRight;
}

void Oscillator::processAdd(float* out1, float* out2, int blockSize) {
float blockIncrement = 1.0 / blockSize;
for (int i = 0; i < blockSize; i++) {
m_phase += m_phaseInc;
while (m_phase > 1) {
m_phase -= 1;
}
float distortedPhase = distortPhase(m_phase, m_pdMode, m_pdDistort);
int integerPhase = distortedPhase * 2048;
float frac = distortedPhase * 2048 - integerPhase;
int integerPhase2 = (integerPhase + 1) % 2048;
float amplitudeLeft = (
m_amplitudeLeft * (1 - i * blockIncrement)
+ m_targetAmplitudeLeft * i * blockIncrement
);
float amplitudeRight = (
m_amplitudeRight * (1 - i * blockIncrement)
+ m_targetAmplitudeRight * i * blockIncrement
);
float outSample = (
k_sineTable2048[integerPhase] * (1 - frac)
+ k_sineTable2048[integerPhase2] * frac
);
out1[i] += outSample * amplitudeLeft;
out2[i] += outSample * amplitudeRight;
}
m_amplitudeLeft = m_targetAmplitudeLeft;
m_amplitudeRight = m_targetAmplitudeRight;
}


Synth::Synth(float sampleRate, std::mt19937& randomEngine)
: m_sampleRate(sampleRate)
{
Expand Down Expand Up @@ -165,6 +197,25 @@ void Synth::process(
}
}

void Synth::processOriginal(
int output_channels,
float** output_buffer,
int frame_count
) {
if (output_channels != 2) {
std::cout << "Output channels is not 2. This shouldn't happen!" << std::endl;
exit(1);
}

for (int j = 0; j < frame_count; j++) {
output_buffer[0][j] = 0;
output_buffer[1][j] = 0;
}
for (auto& oscillator : m_oscillators) {
oscillator->processAddOriginal(output_buffer[0], output_buffer[1], frame_count);
}
}

void Synth::processRealtime(
int outputChannels,
float** outputBuffer,
Expand Down
8 changes: 8 additions & 0 deletions src/Synth.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Oscillator {
public:
Oscillator(float sampleRate, float frequency, float phase);
void processAdd(float* out1, float* out2, int blockSize);
void processAddOriginal(float* out1, float* out2, int blockSize);
void setTargetAmplitudeLeft(float amplitude) { m_targetAmplitudeLeft = amplitude; };
void setTargetAmplitudeRight(float amplitude) { m_targetAmplitudeRight = amplitude; };

Expand All @@ -21,6 +22,7 @@ class Oscillator {
const float m_sampleRate;
float m_phase = 0;
const float m_frequency;
const float m_phaseInc;
float m_amplitudeLeft = 0.0;
float m_targetAmplitudeLeft = 0.0;
float m_amplitudeRight = 0.0;
Expand Down Expand Up @@ -48,6 +50,12 @@ class Synth {
int frame_count
);

void processOriginal(
int output_channels,
float** output_buffer,
int frame_count
);

void processRealtime(
int output_channels,
float** output_buffer,
Expand Down
44 changes: 44 additions & 0 deletions src/benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <benchmark/benchmark.h>
#include "../Synth.hpp"

static void benchSynthProcess(benchmark::State& state) {
std::mt19937 randomEngine(0);
Synth synth(48000, randomEngine);

for (int i = 0; i < synth.getNumOscillators(); i++) {
synth.setOscillatorAmplitude(i, 1, 1);
}

int frameCount = 64;
float outputBufferLeft[64];
float outputBufferRight[64];
float* outputBuffer[2] = { outputBufferLeft, outputBufferRight };

for (auto _ : state) {
synth.process(2, outputBuffer, frameCount);
}
}
// Register the function as a benchmark
BENCHMARK(benchSynthProcess);

static void benchSynthProcessOriginal(benchmark::State& state) {
std::mt19937 randomEngine(0);
Synth synth(48000, randomEngine);

for (int i = 0; i < synth.getNumOscillators(); i++) {
synth.setOscillatorAmplitude(i, 1, 1);
}

int frameCount = 64;
float outputBufferLeft[64];
float outputBufferRight[64];
float* outputBuffer[2] = { outputBufferLeft, outputBufferRight };

for (auto _ : state) {
synth.processOriginal(2, outputBuffer, frameCount);
}
}
// Register the function as a benchmark
BENCHMARK(benchSynthProcessOriginal);

BENCHMARK_MAIN();
2 changes: 1 addition & 1 deletion tests/test_canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,4 @@ def test_image_to_sound_regression(canvas, gradient_image, write_regtests):
expected_sound, expected_rate = soundfile.read(regression_test_file)

assert rate == expected_rate
np.testing.assert_allclose(sound, expected_sound)
np.testing.assert_allclose(sound, expected_sound, rtol=0, atol=1e-6)
1 change: 1 addition & 0 deletions third_party/benchmark
Submodule benchmark added at 2d054b