diff options
author | Samuel Johnson <[email protected]> | 2025-05-19 02:49:42 -0400 |
---|---|---|
committer | Samuel Johnson <[email protected]> | 2025-05-19 02:49:42 -0400 |
commit | 886b6573ebdcf00bf862aa03bf07fa0a3469a86d (patch) | |
tree | 7be8e187e5d0aab86611b8c00e63db9bfa82605d | |
parent | ca7ee50998d59951d46647f0d45258f1a4c21b06 (diff) |
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 21 | ||||
-rw-r--r-- | examples/test.c | 134 | ||||
-rw-r--r-- | mmband/adsr.c | 9 | ||||
-rw-r--r-- | mmband/api/adsr.h | 2 | ||||
-rw-r--r-- | mmband/api/instrument.h | 2 | ||||
-rw-r--r-- | mmband/audio_player.c | 4 | ||||
-rw-r--r-- | mmband/instrument.c | 13 | ||||
-rw-r--r-- | mmband/waves/none.c | 2 | ||||
-rw-r--r-- | mmband/waves/waveform.h | 2 |
10 files changed, 170 insertions, 22 deletions
diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index f84692f..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "vendor/portaudio"] - path = vendor/portaudio - url = https://github.com/PortAudio/portaudio diff --git a/CMakeLists.txt b/CMakeLists.txt index b476823..c564c75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,13 @@ project(mmband VERSION 0.1) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) add_library(${PROJECT_NAME} SHARED - ${PROJECT_NAME}/audio_player.c ${PROJECT_NAME}/instrument.c + ${PROJECT_NAME}/adsr.c + ${PROJECT_NAME}/waves/none.c + ${PROJECT_NAME}/waves/sine.c + ${PROJECT_NAME}/waves/square.c + ${PROJECT_NAME}/waves/saw.c + ${PROJECT_NAME}/waves/triangle.c ) target_include_directories(${PROJECT_NAME} PUBLIC .) @@ -16,6 +21,18 @@ set_target_properties(${PROECT_NAME} PROPERTIES COMPILE_WARNING_AS_ERROR ON ) +add_executable(examples + examples/test.c +) + +target_include_directories(examples PUBLIC .) +set_target_properties(examples PROPERTIES + C_STANDARD 99 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF + COMPILE_WARNING_AS_ERROR ON +) + add_subdirectory(vendor/portaudio) -target_link_libraries(${PROJECT_NAME} portaudio) +target_link_libraries(examples ${PROJECT_NAME} portaudio) diff --git a/examples/test.c b/examples/test.c new file mode 100644 index 0000000..05c5114 --- /dev/null +++ b/examples/test.c @@ -0,0 +1,134 @@ +#include "mmband/api/adsr.h" +#include <stdio.h> +#include <stdlib.h> + +#include <portaudio.h> +#include <mmband/api/instrument.h> + +#define SAMPLE_RATE 44100 +#define FRAMES_PER_BUFFER 512 + +// TODO: make adsr depend on sample rate + +int main (void) { + PaStream *stream; + PaError err = Pa_Initialize(); + if (err != paNoError) { + printf("PortAudio error: %s\n", Pa_GetErrorText(err)); + return 1; + } + + PaStreamParameters output_params; + output_params.device = Pa_GetDefaultOutputDevice(); + output_params.channelCount = 2; + output_params.sampleFormat = paFloat32; + output_params.suggestedLatency = Pa_GetDeviceInfo(output_params.device)->defaultHighInputLatency; + output_params.hostApiSpecificStreamInfo = NULL; + + printf("Opening stream.\n"); + err = Pa_OpenStream( + &stream, + NULL, + &output_params, + SAMPLE_RATE, + FRAMES_PER_BUFFER, + paClipOff, + NULL, + NULL + ); + if (err != paNoError) { + printf("PortAudio error: %s\n", Pa_GetErrorText(err)); + return 1; + } + + instrument_ref instrument = ins_new(); + + ins_set_carrier(instrument, OSC_SINE); + ins_set_modulator(instrument, OSC_SINE); + ins_set_carrier_amplitude(instrument, 0.25); + ins_set_modulator_amplitude(instrument, 0.25); + ins_set_frequency_mult(instrument, 3.0); + + adsr_ref adsr = adsr_new(); + + adsr_set_attack(adsr, 0.2); + adsr_set_decay(adsr, 0.2); + adsr_set_sustain(adsr, 0.85); + adsr_set_release(adsr, 0.5); + + int switch_frames = (60.0 / 120.0) * SAMPLE_RATE; + int iteration = 0; + int state = 0; + + printf("Starting stream.\n"); + err = Pa_StartStream(stream); + if (err != paNoError) { + printf("PortAudio error: %s\n", Pa_GetErrorText(err)); + return 1; + } + + ins_set_frequency(instrument, 246.9); + for (int i = 0; i < (60 * SAMPLE_RATE) / FRAMES_PER_BUFFER; ++i) { + float buffer[FRAMES_PER_BUFFER][2]; + for (int j = 0; j < FRAMES_PER_BUFFER; j++) { + iteration++; + + if (iteration >= switch_frames) { + switch (state) { + case 0: + ins_set_frequency(instrument, 329.6); + //adsr_reset(adsr); + state++; + break; + case 1: + ins_set_frequency(instrument, 370.0); + //adsr_reset(adsr); + state++; + break; + case 2: + ins_set_frequency(instrument, 440.0); + //adsr_reset(adsr); + state++; + break; + case 3: + ins_set_frequency(instrument, 370.0); + //adsr_reset(adsr); + state++; + break; + case 4: + ins_set_frequency(instrument, 329.6); + //adsr_reset(adsr); + state++; + break; + default: + ins_set_frequency(instrument, 246.9); + //adsr_reset(adsr); + state = 0; + break; + } + + iteration = 0; + } + + //float env = adsr_tick(adsr, SAMPLE_RATE); + float ins = ins_tick(instrument, SAMPLE_RATE); + buffer[j][0] = ins;// * env; + buffer[j][1] = ins;// * env; + } + + err = Pa_WriteStream(stream, buffer, FRAMES_PER_BUFFER); + if (err != paNoError) { + printf("PortAudio error: %s\n", Pa_GetErrorText(err)); + return 1; + } + } + + Pa_StopStream(stream); + Pa_CloseStream(stream); + + adsr_free(adsr); + ins_free(instrument); + + Pa_Terminate(); + return 0; +} diff --git a/mmband/adsr.c b/mmband/adsr.c index b2a22e6..b27d1fb 100644 --- a/mmband/adsr.c +++ b/mmband/adsr.c @@ -1,6 +1,7 @@ #include <math.h> #include <stdbool.h> #include <stdlib.h> +#include <stdio.h> #include <mmband/api/adsr.h> @@ -75,10 +76,10 @@ void adsr_gate (adsr_ref adsr) { } } -float adsr_tick (adsr_ref adsr) { +float adsr_tick (adsr_ref adsr, int sample_rate) { switch (adsr->state) { case ADSR_ATTACK: - adsr->out = adsr->attack_base + adsr->out * adsr->attack_curve; + adsr->out = adsr->attack_base + adsr->out * (adsr->attack_curve / sample_rate); if (adsr->out >= 1.0) { adsr->out = 1.0; @@ -87,7 +88,7 @@ float adsr_tick (adsr_ref adsr) { break; case ADSR_DECAY: - adsr->out = adsr->decay_base + adsr->out * adsr->decay_curve; + adsr->out = adsr->decay_base + adsr->out * (adsr->decay_curve / sample_rate); if (adsr->out <= adsr->sustain) { adsr->out = adsr->sustain; @@ -96,7 +97,7 @@ float adsr_tick (adsr_ref adsr) { break; case ADSR_RELEASE: - adsr->out = adsr->release_base + adsr->out * adsr->release_curve; + adsr->out = adsr->release_base + adsr->out * (adsr->release_curve / sample_rate); if (adsr->out <= 0.0) { adsr->out = 0.0; diff --git a/mmband/api/adsr.h b/mmband/api/adsr.h index 62b58d2..cc2dee6 100644 --- a/mmband/api/adsr.h +++ b/mmband/api/adsr.h @@ -10,7 +10,7 @@ MMAPI void adsr_free (adsr_ref adsr); MMAPI void adsr_reset (adsr_ref adsr); MMAPI void adsr_gate (adsr_ref adsr); -MMAPI float adsr_tick (adsr_ref adsr); +MMAPI float adsr_tick (adsr_ref adsr, int sample_rate); MMAPI void adsr_set_attack (adsr_ref adsr, float attack_rate); MMAPI void adsr_set_decay (adsr_ref adsr, float decay_rate); diff --git a/mmband/api/instrument.h b/mmband/api/instrument.h index bad0d48..3190d10 100644 --- a/mmband/api/instrument.h +++ b/mmband/api/instrument.h @@ -39,7 +39,7 @@ MMAPI void ins_set_modulator (instrument_ref instrument, enum osc MMAPI void ins_set_carrier_amplitude (instrument_ref instrument, float amplitude); MMAPI void ins_set_carrier_frequency (instrument_ref instrument, float amplitude); MMAPI void ins_set_modulator_amplitude (instrument_ref instrument, float amplitude); -MMAPI void ins_set_frequency_ratio (instrument_ref instrument, float ratio); +MMAPI void ins_set_frequency_mult (instrument_ref instrument, float mult); MMAPI void ins_set_frequency (instrument_ref instrument, float frequency); MMAPI float ins_tick (instrument_ref instrument, int sample_rate); diff --git a/mmband/audio_player.c b/mmband/audio_player.c deleted file mode 100644 index 3b257a4..0000000 --- a/mmband/audio_player.c +++ /dev/null @@ -1,4 +0,0 @@ -// dummy function for initial commit -int add (int a, int b) { - return a + b; -} diff --git a/mmband/instrument.c b/mmband/instrument.c index 38c7d43..2ec9821 100644 --- a/mmband/instrument.c +++ b/mmband/instrument.c @@ -1,5 +1,6 @@ #include <math.h> #include <stdlib.h> +#include <stdio.h> #include <mmband/api/instrument.h> #include <mmband/api/adsr.h> @@ -18,7 +19,7 @@ struct instrument { struct oscillation carrier; struct oscillation modulator; - float frequency_ratio; + float frequency_mult; }; float osc_tick (struct oscillation *osc, int sample_rate) { @@ -55,7 +56,7 @@ float modulate (struct oscillation *carrier, struct oscillation *modulator, int instrument_ref ins_new () { instrument_ref instrument = malloc(sizeof(struct instrument)); - instrument->frequency_ratio = 1.0; + instrument->frequency_mult = 1.0; instrument->carrier.type = OSC_SINE; instrument->carrier.amplitude = 0.0; @@ -92,17 +93,17 @@ void ins_set_carrier_amplitude (instrument_ref instrument, float amplitude) { instrument->carrier.amplitude = amplitude; } -void ins_set_modulator_aplitude (instrument_ref instrument, float amplitude) { +void ins_set_modulator_amplitude (instrument_ref instrument, float amplitude) { instrument->modulator.amplitude = amplitude; } -void ins_set_frequency_ratio (instrument_ref instrument, float frequency_ratio) { - instrument->frequency_ratio = frequency_ratio; +void ins_set_frequency_mult (instrument_ref instrument, float frequency_mult) { + instrument->frequency_mult = frequency_mult; } void ins_set_frequency (instrument_ref instrument, float frequency) { instrument->carrier.frequency = frequency; - instrument->modulator.frequency = frequency * instrument->frequency_ratio; + instrument->modulator.frequency = frequency * instrument->frequency_mult; } float ins_tick (instrument_ref instrument, int sample_rate) { diff --git a/mmband/waves/none.c b/mmband/waves/none.c index 110dc1c..4526e8f 100644 --- a/mmband/waves/none.c +++ b/mmband/waves/none.c @@ -1,6 +1,6 @@ #include <mmband/waves/waveform.h> -float zero (float phase) { +float none (float phase) { (void) phase; return 0.0; diff --git a/mmband/waves/waveform.h b/mmband/waves/waveform.h index df18e36..cb7128c 100644 --- a/mmband/waves/waveform.h +++ b/mmband/waves/waveform.h @@ -1,6 +1,8 @@ #ifndef MMBAND_WAVEFORM_H #define MMBAND_WAVEFORM_H +#include <mmband/api/lib.h> + typedef float wave_function (float); wave_function none; |