jstrait / wavefile

A Ruby gem for reading and writing sound files in Wave format (*.wav)
https://wavefilegem.com
MIT License
208 stars 24 forks source link

Method to obtain markers/cue points #26

Open djevo1 opened 7 years ago

djevo1 commented 7 years ago

Is wavefile able to read cue/marker points from wave files. I have seen very little on this topic and am curious if wavefile would support this.

jstrait commented 7 years ago

@djevo1 the gem doesn't support reading cue/marker points from wave files. I don't think there's a fundamental reason why the gem couldn't support this in the future, but I'm not very familiar with this type of chunk and haven't personally had a reason to use it myself before.

Have you used wave file cue points before? If the gem supported reading cue points from wave files, is there a particular use case you would have in mind?

zoras commented 7 years ago

@jstrait I was looking for the same as I want to split a portion of the wave file. BTW how do I split wave file? I didn't find any example for splitting files.

jstrait commented 7 years ago

@zoras can you say more about how you are wanting to split the file? Are you wanting to split it based on cue/marker points? Or some different way? What is the bigger thing you are trying to accomplish by splitting the file? (Just asking because it might help me give a better answer).

As an example, if you wanted to split a file so that every 100,000 samples went to a different file, this is one way you could do it:

require 'wavefile'
include WaveFile

SAMPLE_FRAMES_PER_FILE = 100000
OUTPUT_FORMAT = Format.new(:stereo, :pcm_16, 44100)

file_name = "input_file.wav"
file_index = 1

Reader.new(file_name).each_buffer(SAMPLE_FRAMES_PER_FILE) do |buffer|
  Writer.new("output_file_#{file_index}.wav", OUTPUT_FORMAT) do |writer|
    writer.write(buffer)
  end

  file_index += 1
end
zoras commented 7 years ago

@jstrait I am working with wavefile and wanted to trim the audio file let's say of 10:00 minutes from 3:00 to 7:00 mins. At the moment, I'm using audio-trimmer to accomplish the same.

jstrait commented 7 years ago

@zoras there's not a direct way to do that, but you could do it like this:

  1. Read sample frames (but throw them away) until you reach the starting trim point
  2. Next, read sample frames until the ending trim point, and write them to the output file.

For example, something like this:

require 'wavefile'
include WaveFile

STARTING_NUMBER_OF_SECONDS = 3 * 60   # Starting point is 3 minutes into file
ENDING_NUMBER_OF_SECONDS = 7 * 60     # Ending point is 7 minutes into file

Reader.new("file_to_trim.wav") do |reader|
  STARTING_SAMPLE_FRAME = reader.format.sample_rate * STARTING_NUMBER_OF_SECONDS
  ENDING_SAMPLE_FRAME = reader.format.sample_rate * ENDING_NUMBER_OF_SECONDS

  # Read up to the starting trim point
  throwaway_buffer = reader.read(STARTING_SAMPLE_FRAME)

  Writer.new("trimmed_file.wav", reader.format) do |writer|
    buffer = reader.read(ENDING_SAMPLE_FRAME - STARTING_SAMPLE_FRAME)
    writer.write(buffer)
  end
end

Hope that helps!

henrikj242 commented 6 years ago

I just added loop information extraction in another project. I've forked this repo and expect to implement the same here :)