### Decode and Play Sound with Low-Level API Source: https://github.com/mackron/miniaudio/blob/master/README.md Shows how to decode and play an audio file using the low-level miniaudio API. This example requires a file path as a command-line argument. It involves initializing a decoder, configuring a playback device, and starting playback. ```c #include "miniaudio/miniaudio.h" #include void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData; if (pDecoder == NULL) { return; } ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount, NULL); (void)pInput; } int main(int argc, char** argv) { ma_result result; ma_decoder decoder; ma_device_config deviceConfig; ma_device device; if (argc < 2) { printf("No input file.\n"); return -1; } result = ma_decoder_init_file(argv[1], NULL, &decoder); if (result != MA_SUCCESS) { return -2; } deviceConfig = ma_device_config_init(ma_device_type_playback); deviceConfig.playback.format = decoder.outputFormat; deviceConfig.playback.channels = decoder.outputChannels; deviceConfig.sampleRate = decoder.outputSampleRate; deviceConfig.dataCallback = data_callback; deviceConfig.pUserData = &decoder; if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) { printf("Failed to open playback device.\n"); ma_decoder_uninit(&decoder); return -3; } if (ma_device_start(&device) != MA_SUCCESS) { printf("Failed to start playback device.\n"); ma_device_uninit(&device); ma_decoder_uninit(&decoder); return -4; } printf("Press Enter to quit..."); getchar(); ma_device_uninit(&device); ma_decoder_uninit(&decoder); return 0; } ``` -------------------------------- ### Build miniaudio examples Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Enables the building of all miniaudio examples if MINIAUDIO_BUILD_EXAMPLES is set. It defines a helper function and then calls it for various example source files. ```cmake if (MINIAUDIO_BUILD_EXAMPLES) set(EXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples) function(add_miniaudio_example name source) add_executable(${name} ${EXAMPLES_DIR}/${source}) target_link_libraries(${name} PRIVATE miniaudio_common_options) endfunction() add_miniaudio_example(miniaudio_custom_backend custom_backend.c) add_miniaudio_example(miniaudio_custom_decoder_engine custom_decoder_engine.c) if(HAS_LIBVORBIS) target_link_libraries(miniaudio_custom_decoder_engine PRIVATE libvorbis_interface) else() target_compile_definitions(miniaudio_custom_decoder_engine PRIVATE MA_NO_LIBVORBIS) message(STATUS "miniaudio_libvorbis is disabled. Vorbis support is disabled in miniaudio_custom_decoder_engine.") endif() if(HAS_LIBOPUS) target_link_libraries(miniaudio_custom_decoder_engine PRIVATE libopus_interface) else() target_compile_definitions(miniaudio_custom_decoder_engine PRIVATE MA_NO_LIBOPUS) message(STATUS "miniaudio_libopus is disabled. Opus support is disabled in miniaudio_custom_decoder_engine.") endif() add_miniaudio_example(miniaudio_custom_decoder custom_decoder.c) if(HAS_LIBVORBIS) target_link_libraries(miniaudio_custom_decoder PRIVATE libvorbis_interface) else() target_compile_definitions(miniaudio_custom_decoder PRIVATE MA_NO_LIBVORBIS) message(STATUS "miniaudio_libvorbis is disabled. Vorbis support is disabled in miniaudio_custom_decoder.") endif() if(HAS_LIBOPUS) target_link_libraries(miniaudio_custom_decoder PRIVATE libopus_interface) else() target_compile_definitions(miniaudio_custom_decoder PRIVATE MA_NO_LIBOPUS) message(STATUS "miniaudio_libopus is disabled. Opus support is disabled in miniaudio_custom_decoder.") endif() add_miniaudio_example(miniaudio_data_source_chaining data_source_chaining.c) add_miniaudio_example(miniaudio_duplex_effect duplex_effect.c) add_miniaudio_example(miniaudio_engine_advanced engine_advanced.c) add_miniaudio_example(miniaudio_engine_effects engine_effects.c) add_miniaudio_example(miniaudio_engine_hello_world engine_hello_world.c) if(HAS_SDL2) add_miniaudio_example(miniaudio_engine_sdl engine_sdl.c) target_link_libraries(miniaudio_engine_sdl PRIVATE ${SDL2_LIBRARY}) else() message(STATUS "SDL2 could not be found. miniaudio_engine_sdl has been excluded.") endif() if(HAS_STEAMAUDIO) add_miniaudio_example(miniaudio_engine_steamaudio engine_steamaudio.c) target_include_directories(miniaudio_engine_steamaudio PRIVATE ${STEAMAUDIO_INCLUDE_DIR}) target_link_libraries (miniaudio_engine_steamaudio PRIVATE ${STEAMAUDIO_LIBRARY}) else() message(STATUS "SteamAudio could not be found. miniaudio_engine_steamaudio has been excluded.") endif() add_miniaudio_example(miniaudio_hilo_interop hilo_interop.c) add_miniaudio_example(miniaudio_node_graph node_graph.c) add_miniaudio_example(miniaudio_resource_manager_advanced resource_manager_advanced.c) add_miniaudio_example(miniaudio_resource_manager resource_manager.c) add_miniaudio_example(miniaudio_simple_capture simple_capture.c) add_miniaudio_example(miniaudio_simple_duplex simple_duplex.c) add_miniaudio_example(miniaudio_simple_enumeration simple_enumeration.c) add_miniaudio_example(miniaudio_simple_loopback simple_loopback.c) add_miniaudio_example(miniaudio_simple_looping simple_looping.c) add_miniaudio_example(miniaudio_simple_mixing simple_mixing.c) add_miniaudio_example(miniaudio_simple_playback_sine simple_playback_sine.c) add_miniaudio_example(miniaudio_simple_playback simple_playback.c) add_miniaudio_example(miniaudio_simple_spatialization simple_spatialization.c) endif() ``` -------------------------------- ### Install miniaudio Package and Libraries Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt This section handles the installation of the generated miniaudio.pc file to the pkg-config directory and installs the miniaudio library targets. It uses the MINIAUDIO_INSTALL variable to control whether installation is performed. ```cmake if(MINIAUDIO_INSTALL) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/miniaudio.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") message(STATUS "Library list: ${LIBS_TO_INSTALL}") install(TARGETS ${LIBS_TO_INSTALL} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) endif() ``` -------------------------------- ### Add miniaudio example executable Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Defines a function to add miniaudio examples as executables. It links against common miniaudio options. ```cmake function(add_miniaudio_example name source) add_executable(${name} ${EXAMPLES_DIR}/${source}) target_link_libraries(${name} PRIVATE miniaudio_common_options) endfunction() ``` -------------------------------- ### Test Execution Setup Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Enables testing and defines a helper function `add_miniaudio_test` to create executables for tests. It links tests against `miniaudio_common_options`. ```cmake if(MINIAUDIO_BUILD_TESTS) enable_testing() set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests) function(add_miniaudio_test name source) add_executable(${name} ${TESTS_DIR}/${source}) target_link_libraries(${name} PRIVATE miniaudio_common_options) endfunction() # Disable C++ tests when forcing C89. This is needed because we'll be passing -std=c89 which will cause errors when trying to compile a C++ file. if(NOT MINIAUDIO_FORCE_C89) # The debugging test is only used for debugging miniaudio itself. Don't do add_test() for this, and do not include it in in any automated testing. add_miniaudio_test(miniaudio_debugging debugging/debugging.cpp) add_miniaudio_test(miniaudio_cpp cpp/cpp.cpp) add_test(NAME miniaudio_cpp COMMAND miniaudio_cpp --auto) # This is just the deviceio test. endif() add_miniaudio_test(miniaudio_deviceio deviceio/deviceio.c) add_test(NAME miniaudio_deviceio COMMAND miniaudio_deviceio --auto) add_miniaudio_test(miniaudio_conversion conversion/conversion.c) add_test(NAME miniaudio_conversion COMMAND miniaudio_conversion) add_miniaudio_test(miniaudio_filtering filtering/filtering.c) add_test(NAME miniaudio_filtering COMMAND miniaudio_filtering ${CMAKE_CURRENT_SOURCE_DIR}/data/16-44100-stereo.flac) add_miniaudio_test(miniaudio_generation generation/generation.c) add_test(NAME miniaudio_generation COMMAND miniaudio_generation) endif() ``` -------------------------------- ### Compile with Emscripten Source: https://github.com/mackron/miniaudio/blob/master/tests/_build/README.md Compile a C source file for web deployment using Emscripten. This example enables audio worklets and WASM workers. ```bash emcc ../test_emscripten/ma_test_emscripten.c -o bin/test_emscripten.html -sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY -DMA_ENABLE_AUDIO_WORKLETS -Wall -Wextra ``` -------------------------------- ### Conditional compilation for SDL2 engine example Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Adds the SDL2 engine example if SDL2 is found. It links against the SDL2 library. If SDL2 is not found, a status message is printed. ```cmake if(HAS_SDL2) add_miniaudio_example(miniaudio_engine_sdl engine_sdl.c) target_link_libraries(miniaudio_engine_sdl PRIVATE ${SDL2_LIBRARY}) else() message(STATUS "SDL2 could not be found. miniaudio_engine_sdl has been excluded.") endif() ``` -------------------------------- ### Conditional compilation for SteamAudio engine example Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Adds the SteamAudio engine example if SteamAudio is found. It includes SteamAudio headers and links against the SteamAudio library. If SteamAudio is not found, a status message is printed. ```cmake if(HAS_STEAMAUDIO) add_miniaudio_example(miniaudio_engine_steamaudio engine_steamaudio.c) target_include_directories(miniaudio_engine_steamaudio PRIVATE ${STEAMAUDIO_INCLUDE_DIR}) target_link_libraries (miniaudio_engine_steamaudio PRIVATE ${STEAMAUDIO_LIBRARY}) else() message(STATUS "SteamAudio could not be found. miniaudio_engine_steamaudio has been excluded.") endif() ``` -------------------------------- ### Determine installation library directory for pkg-config Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Sets the MINIAUDIO_PC_LIBDIR variable for pkg-config. It handles both absolute and relative installation paths for the library directory. ```cmake if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") set(MINIAUDIO_PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") else() set(MINIAUDIO_PC_LIBDIR "$exec_prefix/${CMAKE_INSTALL_LIBDIR}") endif() ``` -------------------------------- ### Determine installation include directory for pkg-config Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Sets the MINIAUDIO_PC_INCLUDEDIR variable for pkg-config. It handles both absolute and relative installation paths for the include directory. ```cmake if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") set(MINIAUDIO_PC_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") else() set(MINIAUDIO_PC_INCLUDEDIR "$prefix/${CMAKE_INSTALL_INCLUDEDIR}") endif() ``` -------------------------------- ### 3D Spatialization Setup in miniaudio Source: https://context7.com/mackron/miniaudio/llms.txt Configures listener position, direction, and cone for 3D audio. Loads and positions a sound with attenuation and Doppler effect enabled. ```c #include "miniaudio.h" #include int main(void) { ma_engine engine; ma_sound sound; ma_engine_init(NULL, &engine); /* Position the listener at the origin, facing -Z. */ ma_engine_listener_set_position(&engine, 0, 0.0f, 0.0f, 0.0f); ma_engine_listener_set_direction(&engine, 0, 0.0f, 0.0f, -1.0f); ma_engine_listener_set_world_up(&engine, 0, 0.0f, 1.0f, 0.0f); /* Narrow forward cone: inner 30°, outer 60°, outer gain 0.1. */ ma_engine_listener_set_cone(&engine, 0, 0.523f, /* ~30° inner */ 1.047f, /* ~60° outer */ 0.1f); /* outer gain */ /* Load a sound with spatialization enabled (default). */ ma_sound_init_from_file(&engine, "engine_hum.wav", MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_LOOPING, NULL, NULL, &sound); /* Place sound 10 units to the right. */ ma_sound_set_position(&sound, 10.0f, 0.0f, 0.0f); ma_sound_set_attenuation_model(&sound, ma_attenuation_model_inverse); ma_sound_set_min_distance(&sound, 1.0f); ma_sound_set_max_distance(&sound, 50.0f); ma_sound_set_rolloff(&sound, 1.0f); /* Simulate the sound moving left to right (Doppler). */ ma_sound_set_velocity(&sound, -5.0f, 0.0f, 0.0f); ma_sound_start(&sound); printf("Press Enter to stop...\n"); getchar(); ma_sound_uninit(&sound); ma_engine_uninit(&engine); return 0; } ``` -------------------------------- ### Generate Sine Waveform with miniaudio Source: https://context7.com/mackron/miniaudio/llms.txt Generates a sine waveform using `ma_waveform`. This example initializes a playback device, configures and initializes the waveform, and plays the audio. It also demonstrates dynamically changing the frequency and type of the waveform while it's playing. ```c #include "miniaudio.h" #include #define FORMAT ma_format_f32 #define CHANNELS 2 #define SAMPLE_RATE 48000 void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { ma_waveform_read_pcm_frames((ma_waveform*)pDevice->pUserData, pOutput, frameCount, NULL); (void)pInput; } int main(void) { ma_waveform waveform; ma_waveform_config config; ma_device device; ma_device_config devcfg; devcfg = ma_device_config_init(ma_device_type_playback); devcfg.playback.format = FORMAT; devcfg.playback.channels = CHANNELS; devcfg.sampleRate = SAMPLE_RATE; devcfg.dataCallback = data_callback; devcfg.pUserData = &waveform; if (ma_device_init(NULL, &devcfg, &device) != MA_SUCCESS) return -1; config = ma_waveform_config_init( device.playback.format, device.playback.channels, device.sampleRate, ma_waveform_type_sine, 0.2f, /* amplitude */ 440.0f /* frequency Hz */ ); ma_waveform_init(&config, &waveform); ma_device_start(&device); printf("Playing 440 Hz sine — Press Enter to stop.\n"); getchar(); /* Dynamically change waveform properties while playing. */ ma_waveform_set_frequency(&waveform, 880.0f); ma_waveform_set_type(&waveform, ma_waveform_type_square); printf("Now 880 Hz square — Press Enter to quit.\n"); getchar(); ma_device_uninit(&device); ma_waveform_uninit(&waveform); return 0; } ``` -------------------------------- ### Generate Pink Noise with miniaudio Source: https://context7.com/mackron/miniaudio/llms.txt Generates pink noise using `ma_noise`. This example sets up a playback device and the noise generator, then plays the noise until the user presses Enter. Ensure the correct format, channels, and sample rate are configured for the device. ```c #include "miniaudio.h" #include void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { ma_noise_read_pcm_frames((ma_noise*)pDevice->pUserData, pOutput, frameCount, NULL); (void)pInput; } int main(void) { ma_noise noise; ma_noise_config config; ma_device device; ma_device_config devcfg; devcfg = ma_device_config_init(ma_device_type_playback); devcfg.playback.format = ma_format_f32; devcfg.playback.channels = 2; devcfg.sampleRate = 48000; devcfg.dataCallback = data_callback; devcfg.pUserData = &noise; ma_device_init(NULL, &devcfg, &device); config = ma_noise_config_init( ma_format_f32, 2, ma_noise_type_pink, /* white | pink | brownian */ 0, /* seed (0 = default) */ 0.15f /* amplitude */ ); ma_noise_init(&config, NULL, &noise); ma_device_start(&device); printf("Pink noise — Press Enter to stop.\n"); getchar(); ma_device_uninit(&device); ma_noise_uninit(&noise, NULL); return 0; } ``` -------------------------------- ### Function to Add Extra Nodes Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Defines a CMake function `add_extra_node` to streamline the creation of libraries for extra processing nodes. This function handles library creation, installation, and example executables if enabled. ```cmake function(add_extra_node name) add_library(miniaudio_${name}_node extras/nodes/ma_${name}_node/ma_${name}_node.c extras/nodes/ma_${name}_node/ma_${name}_node.h ) set(libs "${LIBS_TO_INSTALL}") list(APPEND libs miniaudio_${name}_node) set(LIBS_TO_INSTALL "${libs}" PARENT_SCOPE) # without PARENT_SCOPE, any changes are lost if(MINIAUDIO_INSTALL) install(FILES extras/nodes/ma_${name}_node/ma_${name}_node.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/miniaudio/extras/nodes/ma_${name}_node) endif() target_include_directories(miniaudio_${name}_node PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/extras/nodes/ma_${name}_node) target_compile_options (miniaudio_${name}_node PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio_${name}_node PRIVATE ${COMPILE_DEFINES}) if(MINIAUDIO_BUILD_EXAMPLES) add_executable(miniaudio_${name}_node_example extras/nodes/ma_${name}_node/ma_${name}_node_example.c) target_link_libraries(miniaudio_${name}_node_example PRIVATE miniaudio_common_options) endif() endfunction() ``` -------------------------------- ### Configure and Use Data Converter Source: https://context7.com/mackron/miniaudio/llms.txt Shows how to initialize a data converter for sample format, channel count, and sample rate conversion. Includes processing audio frames and retrieving latency information. ```c #include "miniaudio.h" #include #include int main() { /* Convert: s16 mono 44100 Hz → f32 stereo 48000 Hz */ ma_data_converter_config cfg = ma_data_converter_config_init( ma_format_s16, ma_format_f32, 1, 2, 44100, 48000); cfg.resampling.linear.lpfOrder = 8; ma_data_converter converter; ma_result result = ma_data_converter_init(&cfg, NULL, &converter); if (result != MA_SUCCESS) { printf("Converter init failed.\n"); return -1; } /* Source: 1000 s16 mono frames. */ ma_int16* pIn = (ma_int16*)malloc(1000 * sizeof(ma_int16)); /* Destination capacity: ratio = 48000/44100 ≈ 1.088 → ~1089 frames. */ float* pOut = (float*)malloc(1200 * 2 * sizeof(float)); /* Fill pIn with test data (silence). */ for (int i = 0; i < 1000; i++) pIn[i] = 0; ma_uint64 frameCountIn = 1000; ma_uint64 frameCountOut = 1200; result = ma_data_converter_process_pcm_frames( &converter, pIn, &frameCountIn, pOut, &frameCountOut); printf("Consumed %" MA_FMT_UINT64 " input frames, " "produced %" MA_FMT_UINT64 " output frames.\n", frameCountIn, frameCountOut); printf("Input latency: %" MA_FMT_UINT64 " frames\n", ma_data_converter_get_input_latency(&converter)); printf("Output latency: %" MA_FMT_UINT64 " frames\n", ma_data_converter_get_output_latency(&converter)); free(pIn); free(pOut); ma_data_converter_uninit(&converter, NULL); return 0; } ``` -------------------------------- ### Initialize and Use ma_audio_buffer Source: https://context7.com/mackron/miniaudio/llms.txt Demonstrates creating an audio buffer from in-memory sine wave data. Shows how to initialize the buffer, read frames with looping enabled, and seek back to the beginning. ```c #include "miniaudio.h" #include #include int main(void) { /* Generate a short 440 Hz sine burst in memory. */ const ma_uint32 sampleRate = 48000; const ma_uint32 channels = 1; const ma_uint32 frames = sampleRate / 4; /* 250 ms */ float* pSineData = (float*)malloc(frames * sizeof(float)); for (ma_uint32 i = 0; i < frames; i++) pSineData[i] = 0.4f * sinf(2.0f * 3.14159f * 440.0f * i / sampleRate); /* Wrap the existing memory (no copy). */ ma_audio_buffer_config cfg = ma_audio_buffer_config_init( ma_format_f32, channels, frames, pSineData, NULL); ma_audio_buffer buffer; if (ma_audio_buffer_init(&cfg, &buffer) != MA_SUCCESS) return -1; /* Read 1024 frames at a time, looping. */ float out[1024]; ma_uint64 read = ma_audio_buffer_read_pcm_frames(&buffer, out, 1024, /*loop=*/MA_TRUE); printf("Read %" MA_FMT_UINT64 " frames (looped across %" MA_FMT_UINT64 " source frames).\n", read, (ma_uint64)frames); /* Seek back to start. */ ma_audio_buffer_seek_to_pcm_frame(&buffer, 0); ma_audio_buffer_uninit(&buffer); free(pSineData); return 0; } ``` -------------------------------- ### Initialize and Process with ma_resampler Source: https://context7.com/mackron/miniaudio/llms.txt Demonstrates upsampling audio from 22050 Hz to 48000 Hz using the linear algorithm. Shows how to configure the resampler, calculate required input frames, process frames, and dynamically change the sample rate. ```c #include "miniaudio.h" #include #include int main(void) { /* Upsample: s16 stereo 22050 Hz → 48000 Hz */ ma_resampler_config cfg = ma_resampler_config_init( ma_format_s16, 2, /* channels */ 22050, /* input rate */ 48000, /* output rate */ ma_resample_algorithm_linear); cfg.linear.lpfOrder = 4; ma_resampler resampler; if (ma_resampler_init(&cfg, NULL, &resampler) != MA_SUCCESS) return -1; /* How many input frames produce 1024 output frames? */ ma_uint64 required; ma_resampler_get_required_input_frame_count(&resampler, 1024, &required); printf("Need %" MA_FMT_UINT64 " input frames for 1024 output frames.\n", required); ma_int16* pIn = (ma_int16*)calloc(required, 2 * sizeof(ma_int16)); ma_int16* pOut = (ma_int16*)malloc(1024 * 2 * sizeof(ma_int16)); ma_uint64 inCount = required; ma_uint64 outCount = 1024; ma_resampler_process_pcm_frames(&resampler, pIn, &inCount, pOut, &outCount); printf("Produced %" MA_FMT_UINT64 " frames.\n", outCount); /* Change sample rate dynamically. */ ma_resampler_set_rate(&resampler, 22050, 44100); free(pIn); free(pOut); ma_resampler_uninit(&resampler, NULL); return 0; } ``` -------------------------------- ### Initialize Device Configuration Source: https://github.com/mackron/miniaudio/blob/master/CHANGES.md Device configuration initialization now takes only the device type. Other properties are set directly on the returned object. ```c ma_device_config config = ma_device_config_init(ma_device_type_playback); // Set other properties directly on the config object ``` -------------------------------- ### Initialize and Process Audio Filters Source: https://context7.com/mackron/miniaudio/llms.txt Demonstrates initialization and in-place processing for low-pass, high-pass, and band-pass filters. Shows how to re-initialize a filter with new parameters without clearing its state. ```c #include "miniaudio.h" #include int main() { ma_uint32 sampleRate = 48000; ma_uint32 channels = 2; /* ---- Low-pass filter (Butterworth, order 4, cutoff 800 Hz) ---- */ ma_lpf lpf; ma_lpf_config lpfCfg = ma_lpf_config_init(ma_format_f32, channels, sampleRate, 800, 4); ma_lpf_init(&lpfCfg, NULL, &lpf); /* ---- High-pass filter (order 2, cutoff 200 Hz) ---- */ ma_hpf hpf; ma_hpf_config hpfCfg = ma_hpf_config_init(ma_format_f32, channels, sampleRate, 200, 2); ma_hpf_init(&hpfCfg, NULL, &hpf); /* ---- Band-pass filter (order 4, center ~1 kHz) ---- */ ma_bpf bpf; ma_bpf_config bpfCfg = ma_bpf_config_init(ma_format_f32, channels, sampleRate, 1000, 4); ma_bpf_init(&bpfCfg, NULL, &bpf); /* ---- Biquad (manual coefficients — peaking EQ at 2 kHz, +6 dB) ---- */ ma_biquad bq; ma_biquad_config bqCfg = ma_biquad_config_init( ma_format_f32, channels, /* b0 b1 b2 a0 a1 a2 */ 1.0685f, -1.99f, 0.9315f, 1.0f, -1.99f, 0.9315f); ma_biquad_init(&bqCfg, NULL, &bq); /* Process a block of audio in-place (all filters accept same buffer pointer). */ float buf[512 * 2]; /* 512 frames × 2 channels */ /* ... fill buf with source audio ... */ ma_lpf_process_pcm_frames(&lpf, buf, buf, 512); /* LPF in-place */ ma_hpf_process_pcm_frames(&hpf, buf, buf, 512); /* HPF in-place */ /* Result: band-pass effect through chained LP + HP. */ /* Dynamically change cutoff without clearing filter state. */ lpfCfg.cutoffFrequency = 1200; ma_lpf_reinit(&lpfCfg, &lpf); ma_lpf_uninit(&lpf, NULL); ma_hpf_uninit(&hpf, NULL); ma_bpf_uninit(&bpf, NULL); ma_biquad_uninit(&bq, NULL); return 0; } ``` -------------------------------- ### Initialize and Play Sounds with High-Level Engine Source: https://context7.com/mackron/miniaudio/llms.txt Initializes the miniaudio engine and demonstrates playing sounds. Use this for general-purpose audio playback, including background music and sound effects. Requires `miniaudio.h` and `miniaudio.c`. ```c #include "miniaudio.h" #include int main(void) { ma_result result; ma_engine engine; ma_sound sound; /* Initialize engine with default config (uses OS default playback device). */ result = ma_engine_init(NULL, &engine); if (result != MA_SUCCESS) { return -1; } /* Quick fire-and-forget play (no ma_sound needed). */ ma_engine_play_sound(&engine, "background.wav", NULL); /* Full-featured sound: decode into memory, no spatialization. */ result = ma_sound_init_from_file( &engine, "sfx.wav", MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_NO_SPATIALIZATION, NULL, /* sound group */ NULL, /* fence */ &sound); if (result != MA_SUCCESS) { ma_engine_uninit(&engine); return -2; } ma_sound_set_volume(&sound, 0.8f); ma_sound_set_looping(&sound, MA_FALSE); ma_sound_start(&sound); printf("Press Enter to quit...\n"); getchar(); /* Scheduled stop 2 seconds from now (relative to engine global time). */ ma_sound_set_stop_time_in_pcm_frames( &sound, ma_engine_get_time_in_pcm_frames(&engine) + (ma_uint64)ma_engine_get_sample_rate(&engine) * 2); ma_sound_uninit(&sound); ma_engine_uninit(&engine); return 0; } /* Build: cc main.c miniaudio.c -lpthread -lm -o demo */ ``` -------------------------------- ### Device and Context Config Initialization Source: https://github.com/mackron/miniaudio/blob/master/CHANGES.md Configuration initialization functions like ma_device_config_init() and ma_context_config_init() now take fewer parameters, with properties set directly on the config structure. Callback members have been renamed (e.g., onLog to logCallback). ```c // Old: ma_context_config_init(NULL, NULL, onLog); // New: ma_context_config config = ma_context_config_init(); config.logCallback = onLog; ``` -------------------------------- ### Play Sound with High-Level API Source: https://github.com/mackron/miniaudio/blob/master/README.md Demonstrates playing a sound file using the high-level miniaudio engine. Ensure 'sound.wav' is in the same directory or provide a full path. Requires initialization and uninitialization of the engine. ```c #include "miniaudio/miniaudio.h" #include int main() { ma_result result; ma_engine engine; result = ma_engine_init(NULL, &engine); if (result != MA_SUCCESS) { return -1; } ma_engine_play_sound(&engine, "sound.wav", NULL); printf("Press Enter to quit..."); getchar(); ma_engine_uninit(&engine); return 0; } ``` -------------------------------- ### Configure JACK Backend Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Configures the JACK audio backend by finding its library and include paths using PkgConfig and find_library/find_path. It links the JACK library and adds its include directory if available. ```cmake is_backend_enabled(JACK) if (JACK_ENABLED) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_JACK jack) endif() find_library(JACK_LIBRARY NAMES jack HINTS ${PC_JACK_LIBRARY_DIRS} ) if (JACK_LIBRARY) find_path(JACK_INCLUDE_DIR NAMES jack/jack.h HINTS ${PC_JACK_INCLUDE_DIRS} ) target_link_libraries(miniaudio PRIVATE ${JACK_LIBRARY}) target_include_directories(miniaudio PRIVATE ${JACK_INCLUDE_DIR}) list(APPEND LINKED_LIBS jack) endif() endif() ``` -------------------------------- ### Conditional compilation for custom decoder Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Configures the custom decoder example, conditionally linking against libvorbis and libopus if available, or defining preprocessor macros to disable their support. ```cmake add_miniaudio_example(miniaudio_custom_decoder custom_decoder.c) if(HAS_LIBVORBIS) target_link_libraries(miniaudio_custom_decoder PRIVATE libvorbis_interface) else() target_compile_definitions(miniaudio_custom_decoder PRIVATE MA_NO_LIBVORBIS) message(STATUS "miniaudio_libvorbis is disabled. Vorbis support is disabled in miniaudio_custom_decoder.") endif() if(HAS_LIBOPUS) target_link_libraries(miniaudio_custom_decoder PRIVATE libopus_interface) else() target_compile_definitions(miniaudio_custom_decoder PRIVATE MA_NO_LIBOPUS) message(STATUS "miniaudio_libopus is disabled. Opus support is disabled in miniaudio_custom_decoder.") endif() ``` -------------------------------- ### Compile and Run with GCC Source: https://github.com/mackron/miniaudio/blob/master/tests/_build/README.md Compile a C source file using GCC and run the resulting executable. Ensure you are in the build directory. ```bash gcc ../test_deviceio/ma_test_deviceio.c -o bin/test_deviceio -ldl -lm -lpthread -Wall -Wextra -Wpedantic -std=c89 ./bin/test_deviceio ``` -------------------------------- ### Manage Sounds with Sound Groups Source: https://context7.com/mackron/miniaudio/llms.txt Initializes an audio engine and creates two sound groups, 'music' and 'sfx'. Sounds are loaded into their respective groups, and volume/fade properties are set. This demonstrates controlling categories of sounds as a whole. ```c #include "miniaudio.h" #include int main(void) { ma_engine engine; ma_sound_group musicGroup; ma_sound_group sfxGroup; ma_sound music; ma_sound sfx1, sfx2; ma_engine_init(NULL, &engine); /* Create two independent mix groups. */ ma_sound_group_init(&engine, 0, NULL, &musicGroup); ma_sound_group_init(&engine, 0, NULL, &sfxGroup); /* Load sounds into their respective groups. */ ma_sound_init_from_file(&engine, "music.ogg", MA_SOUND_FLAG_STREAM | MA_SOUND_FLAG_NO_SPATIALIZATION, &musicGroup, NULL, &music); ma_sound_init_from_file(&engine, "explosion.wav", MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_NO_SPATIALIZATION, &sfxGroup, NULL, &sfx1); ma_sound_init_from_file(&engine, "footstep.wav", MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_NO_SPATIALIZATION, &sfxGroup, NULL, &sfx2); /* Fade music in over 2 seconds, sfx at full volume. */ ma_sound_set_fade_in_milliseconds(&music, 0.0f, 1.0f, 2000); ma_sound_group_set_volume(&sfxGroup, 0.6f); ma_sound_start(&music); ma_sound_start(&sfx1); ma_sound_start(&sfx2); getchar(); ma_sound_uninit(&sfx2); ma_sound_uninit(&sfx1); ma_sound_uninit(&music); ma_sound_group_uninit(&sfxGroup); ma_sound_group_uninit(&musicGroup); ma_engine_uninit(&engine); return 0; } ``` -------------------------------- ### Find SteamAudio Library and Include Directory Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Configures CMake to search for the SteamAudio library and its header files. It supports custom installation paths and platform-specific locations. ```cmake set(STEAMAUDIO_FIND_LIBRARY_HINTS) list(APPEND STEAMAUDIO_FIND_LIBRARY_HINTS ${CMAKE_CURRENT_SOURCE_DIR}/external/steamaudio/lib/${STEAMAUDIO_ARCH}) if(WIN32) else() list(APPEND STEAMAUDIO_FIND_LIBRARY_HINTS /opt/steamaudio/lib/${STEAMAUDIO_ARCH}) list(APPEND STEAMAUDIO_FIND_LIBRARY_HINTS /usr/local/steamaudio/lib/${STEAMAUDIO_ARCH}) endif() set(STEAMAUDIO_FIND_HEADER_HINTS) list(APPEND STEAMAUDIO_FIND_HEADER_HINTS ${CMAKE_CURRENT_SOURCE_DIR}/external/steamaudio/include) if(WIN32) else() list(APPEND STEAMAUDIO_FIND_HEADER_HINTS /opt/steamaudio/include) list(APPEND STEAMAUDIO_FIND_HEADER_HINTS /usr/local/steamaudio/include) endif() find_library(STEAMAUDIO_LIBRARY NAMES phonon HINTS ${STEAMAUDIO_FIND_LIBRARY_HINTS}) if(STEAMAUDIO_LIBRARY) message(STATUS "Found SteamAudio: ${STEAMAUDIO_LIBRARY}") find_path(STEAMAUDIO_INCLUDE_DIR NAMES phonon.h HINTS ${STEAMAUDIO_FIND_HEADER_HINTS} ) if(STEAMAUDIO_INCLUDE_DIR) message(STATUS "Found phonon.h in ${STEAMAUDIO_INCLUDE_DIR}") set(HAS_STEAMAUDIO TRUE) else() message(STATUS "Could not find phonon.h. miniaudio_engine_steamaudio will be excluded.") endif() else() message(STATUS "SteamAudio not found. miniaudio_engine_steamaudio will be excluded.") endif() ``` -------------------------------- ### Add miniaudio libopus Decoder Library Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Builds the miniaudio libopus decoder library, linking it against the libopus interface. It also handles installation of the header if MINIAUDIO_INSTALL is enabled. ```cmake add_library(miniaudio_libopus extras/decoders/libopus/miniaudio_libopus.c extras/decoders/libopus/miniaudio_libopus.h ) list(APPEND LIBS_TO_INSTALL miniaudio_libopus) if(MINIAUDIO_INSTALL) install(FILES extras/decoders/libopus/miniaudio_libopus.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/miniaudio/extras/decoders/libopus) endif() target_compile_options (miniaudio_libopus PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio_libopus PRIVATE ${COMPILE_DEFINES}) target_link_libraries (miniaudio_libopus PRIVATE libopus_interface) target_include_directories(miniaudio_libopus PUBLIC extras/decoders/libopus/) ``` -------------------------------- ### Compile Simple Playback with GCC Source: https://github.com/mackron/miniaudio/blob/master/examples/build/README.md Basic compilation command for simple_playback.c using GCC. Links against dl, m, and pthread. ```bash gcc ../simple_playback.c -o bin/simple_playback -ldl -lm -lpthread ``` -------------------------------- ### Add miniaudio Static Library Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Defines the main miniaudio static library using its source and header files. It also handles installation of the header if MINIAUDIO_INSTALL is enabled. ```cmake add_library(miniaudio miniaudio.c miniaudio.h ) list(APPEND LIBS_TO_INSTALL miniaudio) if(MINIAUDIO_INSTALL) install(FILES miniaudio.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/miniaudio) endif() target_include_directories(miniaudio PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_options (miniaudio PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio PRIVATE ${COMPILE_DEFINES}) ``` -------------------------------- ### Build and Play Audio Node Graph Source: https://context7.com/mackron/miniaudio/llms.txt This C code demonstrates building an audio processing graph using the miniaudio node graph API. It initializes a node graph, adds a low-pass filter, a delay node, and a splitter node, then connects them to form an audio processing chain. A data source node is initialized from a WAV file, and the graph is connected to an audio playback device. Ensure 'music.wav' exists in the same directory or provide a path as a command-line argument. ```c #include "miniaudio.h" #include #define CHANNELS 2 #define SAMPLE_RATE 48000 static ma_node_graph g_graph; static ma_lpf_node g_lpfNode; static ma_delay_node g_delayNode; static ma_splitter_node g_splitterNode; void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { ma_node_graph_read_pcm_frames(&g_graph, pOutput, frameCount, NULL); (void)pInput; (void)pDevice; } int main(int argc, char** argv) { ma_result result; ma_decoder decoder; ma_data_source_node dsNode; /* 1. Build graph: endpoint ← lpf ← splitter ← data-source ← delay ←/ */ ma_node_graph_config ngConfig = ma_node_graph_config_init(CHANNELS); ma_node_graph_init(&ngConfig, NULL, &g_graph); /* Low-pass filter at 600 Hz, order 8. */ ma_lpf_node_config lpfCfg = ma_lpf_node_config_init(CHANNELS, SAMPLE_RATE, 600, 8); ma_lpf_node_init(&g_graph, &lpfCfg, NULL, &g_lpfNode); ma_node_attach_output_bus(&g_lpfNode, 0, ma_node_graph_get_endpoint(&g_graph), 0); /* Echo/delay: 200 ms, 25% decay. */ ma_delay_node_config delayCfg = ma_delay_node_config_init( CHANNELS, SAMPLE_RATE, (ma_uint32)(SAMPLE_RATE * 0.2f), 0.25f); ma_delay_node_init(&g_graph, &delayCfg, NULL, &g_delayNode); ma_node_attach_output_bus(&g_delayNode, 0, ma_node_graph_get_endpoint(&g_graph), 0); /* Splitter: output 0 → LPF, output 1 → delay. */ ma_splitter_node_config splitCfg = ma_splitter_node_config_init(CHANNELS); ma_splitter_node_init(&g_graph, &splitCfg, NULL, &g_splitterNode); ma_node_attach_output_bus(&g_splitterNode, 0, &g_lpfNode, 0); ma_node_attach_output_bus(&g_splitterNode, 1, &g_delayNode, 0); /* Volume balance between branches. */ ma_node_set_output_bus_volume(&g_lpfNode, 0, 0.6f); ma_node_set_output_bus_volume(&g_delayNode, 0, 0.4f); /* Data-source node from file. */ ma_decoder_config dcfg = ma_decoder_config_init(ma_format_f32, CHANNELS, SAMPLE_RATE); ma_decoder_init_file(argc > 1 ? argv[1] : "music.wav", &dcfg, &decoder); ma_data_source_node_config dnCfg = ma_data_source_node_config_init(&decoder); ma_data_source_node_init(&g_graph, &dnCfg, NULL, &dsNode); ma_node_attach_output_bus(&dsNode, 0, &g_splitterNode, 0); /* 2. Play through a device. */ ma_device_config devCfg = ma_device_config_init(ma_device_type_playback); devCfg.playback.format = ma_format_f32; devCfg.playback.channels = CHANNELS; devCfg.sampleRate = SAMPLE_RATE; devCfg.dataCallback = data_callback; ma_device device; ma_device_init(NULL, &devCfg, &device); ma_device_start(&device); printf("Press Enter to quit...\n"); getchar(); ma_device_uninit(&device); ma_data_source_node_uninit(&dsNode, NULL); ma_splitter_node_uninit(&g_splitterNode, NULL); ma_delay_node_uninit(&g_delayNode, NULL); ma_lpf_node_uninit(&g_lpfNode, NULL); ma_node_graph_uninit(&g_graph, NULL); ma_decoder_uninit(&decoder); return 0; } ``` -------------------------------- ### Add miniaudio libvorbis Decoder Library Source: https://github.com/mackron/miniaudio/blob/master/CMakeLists.txt Builds the miniaudio libvorbis decoder library, linking it against the libvorbis interface. It also handles installation of the header if MINIAUDIO_INSTALL is enabled. ```cmake add_library(miniaudio_libvorbis extras/decoders/libvorbis/miniaudio_libvorbis.c extras/decoders/libvorbis/miniaudio_libvorbis.h ) list(APPEND LIBS_TO_INSTALL miniaudio_libvorbis) if(MINIAUDIO_INSTALL) install(FILES extras/decoders/libvorbis/miniaudio_libvorbis.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/miniaudio/extras/decoders/libvorbis) endif() target_compile_options (miniaudio_libvorbis PRIVATE ${COMPILE_OPTIONS}) target_compile_definitions(miniaudio_libvorbis PRIVATE ${COMPILE_DEFINES}) target_link_libraries (miniaudio_libvorbis PRIVATE libvorbis_interface) target_include_directories(miniaudio_libvorbis PUBLIC extras/decoders/libvorbis/) ```