July 6, 2009
The WaveFile gem has gotten its first update, to version 0.2.0. The biggest news is that it can now properly read and write stereo files. (In fact, it should support files with any number of channels). The code is hosted on GitHub, while the gem is hosted at GitHub hosted at Gemcutter.
For basic usage and installation, check out my previous post on WaveFile 0.1.0. If you already have the old gem, you can update it to v0.2.0 with the following command:
sudo gem update wavefile
For mono files, WaveFile works the same as before - sample values are stored in a flat array. For stereo files, each sample is an array, with a value for the left and right channel.
# A mono file
w_mono = WaveFile.new(1, 44100, 8)
w.sample_data = [0, 128, 255, 128]
# A stereo file
w_stereo = WaveFile.new(2, 44100, 8)
w.sample_data = [[0, 255], [128, 128], [255, 0], [128, 128]]
In each sub-array, the left channel sample comes first, and the right channel is second. (You won’t hear anything if you save and play the files in the example above, since they only contain enough data for 1/11,025th of a second).
Although I haven’t tested it, WaveFile should theoretically support files with an arbitrary number of channels. For example, a quadraphonic file would be represented like below.
w_quad = WaveFile.new(4, 44100, 16)
w.sample_data = [[0, 255, 128, 0], [255, 128, 0, 0], [128, 0, 0, 255], [0, 0, 255, 128]]
This version adds two convenience methods mono?() and stereo?(). These are a more readable equivalent of num_channels == 1 and num_channels == 2, respectively.
w = WaveFile.new(1, 44100, 16)
puts w.mono? # Prints "true"
puts w.stereo? # Prints "false"
You can now pass the symbols :mono and :stereo into the num_channels argument of the constructor, to make the code more readable. The two lines below are equivalent:
w = WaveFile.new(2, 44100, 16)
w = WaveFile.new(:stereo, 44100, 16)
You can now convert files to play backwards, using the new reverse() method. Checking for subliminal messages in your favorites records just became that much easier.
w = WaveFile.open("myfile.wav")
w.reverse()
w.save("myfile_reversed.wav")
Finally, the conversion of raw samples to normalized form, and vice-versa, is more accurate.