Class: BeatsWaveFile
- Inherits:
-
WaveFile
- Object
- WaveFile
- BeatsWaveFile
- Defined in:
- lib/beatswavefile.rb
Overview
Adds some functionality to the WaveFile gem that allows for improved performance. The use of open_for_appending() allows a wave file to be written to disk in chunks, instead of all at once. This improves performance (and I would assume memory usage) by eliminating the need to store the entire sample data for the song in memory in a giant (i.e. millions of elements) array.
I’m not sure these methods in their current form are suitable for the WaveFile gem. If I figure out a better API I might add it to the WaveFile gem in the future, but until then I’m just putting it here. Since BEATS is a stand-alone app and not a re-usable library, I don’t think this should be a problem.
Instance Method Summary collapse
- #calculate_duration(sample_rate, total_samples) ⇒ Object
-
#open_for_appending(path) ⇒ Object
Writes the header for the wave file to path, and returns an open File object that can be used outside the method to append the sample data.
- #write_header(file, sample_length) ⇒ Object
Instance Method Details
#calculate_duration(sample_rate, total_samples) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/beatswavefile.rb', line 47 def calculate_duration(sample_rate, total_samples) samples_per_millisecond = sample_rate / 1000.0 samples_per_second = sample_rate samples_per_minute = samples_per_second * 60 samples_per_hour = samples_per_minute * 60 hours, minutes, seconds, milliseconds = 0, 0, 0, 0 if total_samples >= samples_per_hour hours = total_samples / samples_per_hour total_samples -= samples_per_hour * hours end if total_samples >= samples_per_minute minutes = total_samples / samples_per_minute total_samples -= samples_per_minute * minutes end if total_samples >= samples_per_second seconds = total_samples / samples_per_second total_samples -= samples_per_second * seconds end milliseconds = (total_samples / samples_per_millisecond).floor return { :hours => hours, :minutes => minutes, :seconds => seconds, :milliseconds => milliseconds } end |
#open_for_appending(path) ⇒ Object
Writes the header for the wave file to path, and returns an open File object that can be used outside the method to append the sample data. WARNING: The header contains a field for the total number of samples in the file. This number of samples (and exactly this number of samples) must be subsequently be written to the file before it is closed or it won’t be valid and you won’t be able to play it.
18 19 20 21 22 23 |
# File 'lib/beatswavefile.rb', line 18 def open_for_appending(path) file = File.open(path, "wb") write_header(file, 0) return file end |
#write_header(file, sample_length) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/beatswavefile.rb', line 25 def write_header(file, sample_length) bytes_per_sample = (@bits_per_sample / 8) sample_data_size = sample_length * bytes_per_sample * @num_channels # Write the header header = CHUNK_ID header += [HEADER_SIZE + sample_data_size].pack("V") header += FORMAT header += FORMAT_CHUNK_ID header += [SUB_CHUNK1_SIZE].pack("V") header += [PCM].pack("v") header += [@num_channels].pack("v") header += [@sample_rate].pack("V") header += [@byte_rate].pack("V") header += [@block_align].pack("v") header += [@bits_per_sample].pack("v") header += DATA_CHUNK_ID header += [sample_data_size].pack("V") file.syswrite(header) end |