Closed taf2 closed 7 years ago
Sorry for taking awhile to respond. I can see the benefit of this in theory - is there a specific use case where this would be helpful for you?
Passing in an IO
object to the new
constructors instead of a pathname (as in your examples above) is nice in that it makes the gem agnostic to where it is reading/writing. However, what I don't like as much is that it puts more work on the caller to manually open the file. For my own use, I've only ever wanted to read/write to a file, so this seems like adding extra work without clear gain. Maybe there's a use case I'm not thinking of.
Another option could be to add a different method that allows constructing an instance from an IO
object.
@jstrait - I have a need to avoid writing to disk where were are dealing with a large number wave files and converting them to different formats, downloading the wave file and upload the resulting mp3 for example. With the IO object we can achieve this and avoid touching the disk in the process which improves our throughput.
@taf2 thanks for the additional context, that makes sense.
I've added support for this on the v0.8.0 branch, and it will be included as a feature in that release. I expect it to be released soon.
Out of curiosity, is this still a feature that would be helpful for you for the reasons you mentioned above? It won't change whether this feature gets added either way, I'm just curious how people are using this gem.
Thanks for opening https://github.com/jstrait/wavefile/pull/22 - I appreciate it! I decided to go with that API, where the argument to Reader
/Writer
constructor can either be a String for the file name, or an IO object. I like that because it's backwards compatible with the existing interface.
I ended up building a different implementation though, and added some additional changes:
Reader
or Writer
from an IO
instance, the IO
is intentionally not closed when the Reader
or Writer
is closed. Instead, it needs to be manually closed by the user. Since the user created the IO
externally, the Reader
/Writer
shouldn't make assumptions about what the user wants to do with it.IO
instances that don't support seeking. For example, I don't think you can use a Writer
with a Socket
(although I haven't actually tried it out). The reason is that Wave files include data in the file header about the size of the file, and this can't be known until all data has been written and the Writer
is closed. So when a Writer
is closed it seeks back to the beginning of the IO to update this info. If a future version supports using Reader
to seek to an arbitrary sample frame, this would also be an issue. But at the end of the day, it feels to me like the benefit of supporting other types of IO outweighs this drawback.IO
instance. It now checks if the argument is a String
or not. This seemed to me a little more direct than checking if the argument responds to sysread
or syswrite
, which are more specific implementation details of how the gem works internally. I thought about checking if the argument is a descendent of IO
, but that's not good because StringIO
isn't a subclass of IO
. Reader.file_name
and Writer.file_name
from the v0.8.0 branch, because it doesn't necessarily have a sensible value when reading/writing from an IO, and I don't know of an obvious use case for these fields.Check out the v0.8.0 branch if you're interested to see the current implementation or try it out. Please let me know if you have any feedback.
Because of the alternate implementation, I'll also close https://github.com/jstrait/wavefile/pull/22.
@jstrait - excellent, yeah your implementation is better to leave control of the IO object to the client since they created it. Backwards compatibility is always the way to go thanks!
v0.8.0 has been released, so this feature should now be available. Let me know if you run into any issues!
It would be nice if the interface would allow streaming when reading a wave file.
e.g.
or even more generically from any Ruby IO object: