SoLoud Audio Engine
repository·master·Indexed 24 days ago
https://github.com/jarikomppa/soloudA portable, lightweight C/C++ audio engine designed for game development. Distributed under the Zlib/LibPng license, it provides tools for audio playback, including specialized components like ChipPlayer for AY chip emulation, SNDBUFFER for audio mixing, and a Klatt speech synthesizer.
What's inside SoLoud
- SoLoud is a free, portable C/C++ audio engine designed specifically for games. It is licensed under Zlib/LibPng, making it suitable for various project types. It is designed to be easy to use and highly portable across different platforms.
Install GLEW on Windows
masterTo build or use GLEW on Windows, use the provided project file located in the
build/vc12/directory.use the project file in build/vc12/Build GLEW from scratch with custom extension data
masterTo build GLEW from scratch (for example, to update extension data from the web or add your own extension information), you must have a Unix environment with
wget,perl, andGNU makeinstalled.Regenerate the extension data from the top-level source directory using the
make extensionscommand.make extensionsGenerate glue code for non-C environments using codegen
masterThecodegentool parses SoLoud C++ headers to produce asoloud_codegen.pyfile. This generated Python script can then be used to create various 'glue' code implementations, allowing SoLoud to be used in environments other than C/C++.Install GLEW from a tarball on Unix
masterIf you have downloaded the GLEW tarball from the official website, you can install it on a Unix-based system by running the following commands in sequence:
- Build the project using
make. - Install the library using
sudo -sfollowed bymake install. - Clean up the build files using
make clean.
make sudo -s make install make clean- Build the project using
Use SNDBUFFER for AY sound emulation and rendering
masterThe
SNDBUFFERclass acts as a shared audio buffer for multiple sound sources (like AY chips or beepers) to mix into. It manages sample storage, tracks how many samples are ready for playback, and handles buffer zeroing after samples are read to ensure continuous mixing.Key Workflow
- Initialize: Create an
SNDBUFFERwith a specific size. - Emulation Loop: In your emulation loop, call
count_start()on the buffer, then callcount(source)for each sound source (e.g.,SNDCHIPorSNDRENDER) to let them write to the buffer. - Calculate Ready Samples: Call
count_end()to get the total number of samples ready for playback. - Retrieve Buffers: Use
get_buffers()to get the memory positions and sizes of the contiguous segments ready to be played. - Playback and Reset: Play the retrieved buffers and call
samples_read(count)to notify the buffer that the samples have been consumed, allowing it to zero out that memory for the next mixing cycle.
SNDBUFFER buf(4096); SNDCHIP ay1(buf), ay2(buf); SNDRENDER beeper(buf); // Inside emulation loop for (;;) { // ... emulation logic ... buf.count_start(); buf.count(ay1); buf.count(ay2); buf.count(beeper); unsigned n_samples = buf.count_end(); bufptr_t pos1, pos2; unsigned size1, size2; buf.get_buffers(pos1, size1, pos2, size2, n_samples); // Play the segments wav_play(buf.buffer + pos1, size1); wav_play(buf.buffer + pos2, size2); // Notify buffer to zero out read samples buf.samples_read(n_samples); }- Initialize: Create an
Configure SNDRENDER timing parameters
masterUse
set_timingsto define the relationship between the emulated system's clock and the target audio sample rate. This is critical for correct resampling.Parameters:
sys_clock_rate: The frequency of the emulated system clock (e.g.,SNDR_DEFAULT_SYSTICK_RATEfor a ZX-Spectrum).sample_rate: The target audio sample rate (e.g.,SNDR_DEFAULT_SAMPLE_RATE).
Configure ChipPlayer timings and volumes
masterTo ensure the AY chip emulation runs at the correct speed and volume levels, use the following configuration methods on a
ChipPlayerinstance:set_timings(unsigned system_clock_rate, unsigned chip_clock_rate, unsigned sample_rate): Sets the clock rates for the system, the chip, and the output sample rate.set_volumes(SNDCHIP::CHIP_TYPE t, unsigned global_vol, const SNDCHIP_VOLTAB *vt, const SNDCHIP_PANTAB *pt): Configures the volume tables and global volume for a specific chip type.
Interact with SID registers via read and write
masterFor low-level emulation or direct register control, use the
readandwritemethods to interact with the SID chip's memory map.unsigned char read(unsigned int adr): Reads a byte from the specified address.void write(unsigned int adr, unsigned char byte): Writes a byte to the specified address.
Use the SNDRENDER class for sound resampling
masterThe
SNDRENDERclass is used to convert DAC (Digital-to-Analog Converter) inputs into a PCM buffer, specifically designed for sound resampling in emulation contexts (like the Unreal Speccy project). It manages the relationship between a system clock (e.g., Z80 clock) and the audio sample rate.To use
SNDRENDER, you must provide anSNDBUFFERduring construction. You can then control the emulation process using frame-based updates or direct rendering.Emulate DAC updates with SNDRENDER
masterWhen emulating a system that writes to a DAC, use the following sequence to fill the
SNDBUFFER:start_frame(): Call this at the beginning of an emulation frame. It resets the internal system tick counter to 0.update(unsigned sys_tick, unsigned l, unsigned r): Call this whenever the emulated system writes a new value to the Left (l) or Right (r) DAC channels at a specific system clocksys_tick.end_frame(unsigned endframe_sys_tick): Call this at the end of the frame. It ensures that the last DAC value is emulated (held constant) until the specifiedendframe_sys_tick.
Render synthesized audio to a buffer with TED
masterTo generate audio data from the TED synthesis engine, use
renderSound. This method writes the synthesized samples into a provided buffer.renderSound(unsigned int nrsamples, short *buffer): Rendersnrsamplesinto the providedshortbuffer.storeToBuffer(short *buffer, unsigned int count): Stores the current state/sound to a buffer.