Open DimitriosLisenko opened 3 years ago
Thanks for opening this issue!
Like you pointed out, WaveFile::Reader
currently isn't able to read a .wav file using ~a non-seekable IO
~ an IO
instance that doesn't support pos
. I think this functionality worked correctly in v1.0.1, but was accidentally broken by changes in v1.1.0. I made a proof of concept, similar to your first example, that reads an existing .wav file using popen
. It seems to work with v1.0.1, but with v1.1.0 and v1.1.1 it gives the Illegal seek (Errno::ESPIPE)
error you mentioned above.
require "wavefile"
puts WaveFile::VERSION
sample_frame_count = 0
IO.popen("cat some_file.wav") do |stdout|
WaveFile::Reader.new(stdout).each_buffer do |buffer|
sample_frame_count += buffer.samples.length
end
end
puts "#{sample_frame_count} sample frames read"
Does your original script work when using v1.0.1?
As for whether analyzing an audio recording in realtime is an aim of this project, I would say the gem is agnostic. If sample data is contained in a *.wav file this gem should let you read it out, but what you do with the sample data is an outside concern. When you say realtime, do you mean for the sample data to be streamed continuously while it is being recorded, or do you mean for the entire sample data to be written all at once when recording stops?
One reason I ask is that .wav files don't seem ideal for streaming audio while it is being recorded. The problem is that the beginning of a .wav file includes fields that indicate "chunk" sizes, which are needed to know how much sample data is in the file, and where it is located. If a program records audio and continuously appends it to a .wav file, once recording stops it will have to go back to the beginning of the file and rewrite the correct chunk sizes. However, by this time the beginning of the file has already been streamed. This is more an issue with the .wav file format itself, rather than this gem per se. How does rec
handle this?
(To be clear the issue isn't streaming in general, but streaming a *.wav file that is changing while it is being streamed).
Regardless of whether it solves your ultimate problem, I think it makes sense to fix the bug mentioned above - thanks for pointing it out!
After looking more closely at this, the bug mentioned above more specifically occurs when using an IO
instance that doesn't support pos
, rather than when using a non-seekable IO
per se. (I made a minor update to the comment above to reflect this).
WaveFile::ChunkReaders::RiffReader
internally uses IO.pos
to determine if there are any chunks that occur after the data
chunk. If this is instead accomplished by manually keeping track of how many bytes have been read/are remaining it should be in theory possible to support using IO
instances that don't support pos
.
However, while that should be a fix for some .wav files, there will still probably be an issue with using IO.popen
(and other non-seekable IO instances) if a .wav file has any chunks following the data
chunk. RiffReader
currently uses seek
to read these chunk(s), and (if necessary) to seek back to the start of the data
chunk, and this will cause an error. I think it makes sense to treat that as a separate bug, since fixing the original IO.pos
-related bug will still represent an improvement, and a workaround for the seek issue would require a separate type of fix. (Although a 100% perfect solution is likely not possible due to how *.wav files store their data).
Hello!
I was trying to use this gem to record a wav file to STDOUT and then feed it to
WaveFile::Reader
to analyze in realtime. If I recall correctly, it was something along the lines ofHowever, this results in the following exception:
which is because it's trying to seek on the IO, which is an invalid operation on a pipe.
I did also try record to a file instead of STDOUT and calling WaveFile::Reader on that, but because the file size kept increasing, that also resulted in something going wrong (I think because
WaveFile::Reader#read_until_data_chunk
tries to read until the end of the file). Also that means that the file keeps growing while the recording is ongoing, which is not ideal.I ended up calling
IO.popen("rec -c 1 -t s32 - 2>/dev/null")
which outputs the audio amplitudes as signed 32-bit integers, and analyzing that directly.The reason I'm opening this ticket is because I'm wondering whether analyzing an audio recording in realtime is an aim of this project, and if so, whether it's a planned feature or something that can be done now and I just missed something?
Thank you!