`wavappend()` doesn't update header in certain case
Closed this issue · 8 comments
Hi, everyone.
It seems that the function WAV.wavappend
doesn't update the header information in the following case:
import WAV
x1 = rand(16000)
x2 = rand(16000)
WAV.wavwrite(x1, "test.wav", Fs=16000, nbits=16, compression=WAV.WAVE_FORMAT_PCM)
WAV.wavappend(x2, "test.wav")
The code above correctly appends the data; however, when opening the file with, e.g., Audacity, the program reads the first part of the wave file containing x1
only. I think that the header is not updated correctly. It might have something to do with the compression.
By the way: I'm using Julia-0.6.3 (Windows & Linux).
By the way: reading out the field subchunk2size
by using
header = read("test.wav", 46)
sum(header[41:44] .* (256.^(0:3)))
yields 32000
, which is wrong, since it should be 64000
. (Note: subchunk2size
equals number_samples * number_channels * bits_per_sample / 8
).
I just figured out that the value corresponding to the field chunksize
is correct; however, the value corresponding to subchunk2size
is wrong. My current workaround is as follows:
# Note: `number_samples` and `path_file` is given.
# Read header.
file_stream = open(path_file, "r+")
header = read(file_stream, 46)
# Find characters `data` to determine length (44-bytes or 46-bytes) of header.
# Hex-string below corresponds to the characters `data`.
range_matched_sequence = search(header, [0x64, 0x61, 0x74, 0x61])
if !isempty(range_matched_sequence)
indices_data_size = range_matched_sequence + 4;
if ==(maximum(indices_data_size), 46)
warn("File features 46-byte header.")
end
else
error("Invalid file header.")
end
# Get value that corresponds to field `blockalign`.
block_align = sum(header[33:34] .* (256.^(0:1)))
if ~isinteger(block_align)
error("Corrupted file: non-integer block align.")
end
# Update header.
header[indices_data_size] = reverse(hex2bytes(hex(number_samples*block_align, 8)))
# Overwrite file's header by updated header.
seekstart(file_stream)
write(file_stream, header)
close(file_stream)
This way I avoid reading and writing the whole file.
And by the way: Do you assume 44-byte and/or 46-byte header files?
I skimmed through the code and realized that wavappend
(or even the whole WAV-package) only supports 44-byte headers. (Please correct me if I'm wrong.) If this is the case, I would suggest that the package should either
- throw an error if it appends to a wave file that features a 46-byte header or
- converts the 46-byte header into a 44-byte header as follows:
# `header` is an array containing the first 46 bytes of the wave file
if ==(header[17], 0x12)
warning("Converting 46-byte header into 44-byte header.")
header[17] = 0x10
deleteat!(header, [37,38])
end
Hi, everyone. I've found and fixed the bug related to the aforementioned problem. Please go through my pull-request in order to figure out what I've changed.
Thanks @beyondvoid
It’s been a while since I wrote the header code. I’ll take a look and get back to you.
Hi, @dancasimiro. Thanks for taking a look. If you are interested you can find detailed information on the header at http://soundfile.sapp.org/doc/WaveFormat/.
Fixed by pull request #61.