in creating an example frequency-modulation program, i realized a flaw in the way my library operates. the sine() and cosine() functions take static arguments and generate an array of output samples, but some applications require arguments to change dynamically. for example, to implement frequency (or phase) modulation, the frequency (or phase) of the carrier must vary each sample. this isn't possible the way my sine() and cosine() functions currently operate.
when i was working on vowl, i used a c++ library called the synthesis toolkit (stk). the stk functions i used output one sample at a time, which allows for the level of detail required in many applications.
i decided to modify my functions so that they also only output one sample at a time. i started with the sinusoid functions, which were pretty straightforward to modify. when i moved onto the filters, i figured it would be convenient to implement a general difference equation filter. i created a function called difeq_tick() which generates one filtered sample according to an arbitrary difference equation. this was less straightforward to implement, but it made my code much easier to read. each filter function now generates the coefficients for a specific filter type, and the difeq_tick() function does the filtering.
i've implemented a few simple filters. i started with a 2-point moving average filter, and then tried what i've decided to call a 2-point moving difference filter (not sure if this is the correct terminology). the moving difference filter has a more noticeable effect when applied to an audio file, as it aggresively filters low frequencies and passes high frequencies.
it was very exciting to finally be processing audio with my own programs! this excitement quickly turned into a desire to try out some other filters, so i tried implementing some of the filters from section 6.11 of computer music.
i first tried some basic recursive filters. basic_lp_iir() is 1st-order low-pass filter, and basic_bp_iir() is a 2nd order band-pass filter. i then read further and implemented a 2nd-order butterworth low-pass filter, called butterworth_lp(), a 2nd-order butterworth band-pass filter, called butterworth_bp(), and a 2nd-order butterworth high-pass filter, called butterworth_hp().
while creating these filter functions, i realized that it might be more efficient to create a general difference equation filter function which recieves an array (or two) of coeffecients. i may pursue that option in the future. unrelated to filtering, i also created a makefile to streamline use of the library.
for fun, i recently began writing implementations of various DSP (digital signal-processing) algorithms in C. as there already exist many libraries that streamline the use of such algorithms, and i don't currently have the programming abilities to improve upon them, this project is purely for the sake of education and curiosity.
i began by writing two functions. the wav_read() function parses a WAVE file and stores the parsed data in a wav_data structure. the wav_write function accepts a wav_data structure and creates a WAVE file. writing these functions required that i better understand how WAVE files are structured. i referenced this website heavily.
in learning more about the structure of WAVE files, i came to understand that i would need to properly interpret and scale the samples stored in the data subchunk if i wanted to work with them as floating point values between 1.0 and -1.0. to do this, i wrote two more functions called sample_scale() and float_scale(). sample_scale() accepts a wave_data structure and returns an array containing the audio samples stored as 64-bit floating-point values between 1.0 and -1.0. float_scale() reverses this process, accepting an array of 64-bit floats and a destination wav_data structure, scaling the audio samples back up and storing them into the wav_data structure.
now that i've written these utility functions, i can begin learning how to implement some funky DSP algorithms. :D