-
Notifications
You must be signed in to change notification settings - Fork 104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2-dimensional indexing on SoundFile objects? #15
Comments
You are correct, that insofar as reading the file is concerned, two dimensional indexing is no advantage to just reading all the channels. However, I think it is much more convenient and much easier to understand to write
instead of
In ac983e5 , I implemented two dimensional indexing simply as syntactic sugar that converts the first expression into the second. The whole numpy array is still read, and the second index is only applied after the whole data was read. Indeed, libsndfile does not provide a way to access single channels anyway, so this is probably the only possible solution. |
As for wavread-like functionality, I don't see much difference between
and
or
Do you think |
True. But what about this:
In this hypothetical case,
This wouldn't be the most common use, though, the most common would be:
... which in my opinion easier to grasp then
or
And, just to be clear, I don't suggest to abandon the class
I guess this is better than before, because only allowing But not caching the data also seems strange, especially if someone So probably if a subset of channels is selected they should be copied All in all, regardless of the chosen syntax, I think it is impossible |
I think I finally get your point. Just to make sure: You are saying that indexing a SoundFile object just like a Numpy array is unintuitive, and doing the same on a Numpy array would be better. I can agree with that. However, I think indexing the SoundFile object is extremely convenient and one of the core features of PySoundFile. Also, as I said, there is no way to read single channels in portaudio, so we'll have to live with the inefficiencies this affords us. That said, we could easily allocate a new array instead of returning the view. Did you really run into that problem though? Because I have quite a few friends who work with audio stuff and this is the least of their worries. |
Also, I think there is some confusion regarding the lifetime of SoundFile objects:
are equivalent, and both SoundFile objects will deallocate right on that very line. They will not stay in memory beyond that and the file will not be kept open. I see no reason at all to change this to
If you really want |
In order to be able to give examples for my answer here I tried the two-dimensional feature and promptly found a bug. In line 445 instead of
you should write
Otherwise, whenever you request the first channel ( This is not a biggie, bugs happen all the time, but it illustrates my point: You are implementing stuff that's already implemented in NumPy! I deliberately didn't open a new issue for that because I think the best fix is to remove the code completely. About indexing being intuitive: About indexing being convenient: About returning new memory: It is impossible with libsndfile to read single channels therefore PySoundFile shouldn't claim to do it either. Regarding lifetime: Of course the Example (with my strange test file, 15 frames, 7 channels):
The two buffers hold the same data (the whole file contents) but at separate memory locations:
If PySoundFile would never return single channels (which I strongly suggest), this can still happen but then It's the user's fault. Regarding the necessity of a Yes! I really want (even need) such a thing! I'm trying to convert people from using Matlab to using Python+NumPy+... and every obstacle will make it harder for them and therefore for me. Of course it would be easy for me to implement it locally, but regardless how trivial it may be, I'll have to do this for each project, for each example I show someone, each time I quickly want to try something, ... Don't get me wrong, I definitely don't want a Matlab-clone, I just want a clear and easy high-level interface (in addition to a fully-fledged low-level interface). In closing: |
Thank you very much for pointing out that bug! Quite a nasty one, that. I fondly remember working with Lua, where only |
Regarding
Looks good to me. |
Regarding indexing: I understand everything you are saying, but I really want that feature. As you rightly point out, there are many issues with indexing in general, and two-dimensional indexing in particular, but that feature is just incredibly powerful for my particular use cases. It is implemented as a simple wrapper over In the end, I think this comes down to the same point you were making about |
Responding as per your Email, Basti, I think I agree on all points here: a trivial read function is quite frankly practical, and if it's so simple why not include it? But the indexing is also quite practical, if, as it turns out, somewhat problematic. However, if I wanted to index separate non-neighbouring channels I would instinctively just get the entire numpy array and index from that, as opposed to the example given by mgeier. Put differently: I don't think I would use two-dimensional indexing on a |
I guess both features ( @bastibe: just out of curiosity ... can you give an example where indexing into a |
@mgeier Basically, any time I want to access only part of a file:
This will only read the second second of the file, without reading the second before or anything after. You could also write it like this:
But I think the first example is much cleaner and easier to understand. I had one application that was churning through some 3000 audio files on 8 simultaneus threads. This application was wicked fast and used next to no memory, mainly because PySoundFile allowed us to only load a tiny part of a file at a time and never having to do big allocations. Also, the algorithm could only ever process 1024 samples at a time anyway, so loading more than that would have been a waste. On a different note, Indexing on the other hand is a deterministic operation that will always do the same thing. You can pass the SoundFile object into some random function and have it play back the file, while simultaneusly doing some signal processing with it on the main thread. This works even for very large files that you wouldn't want to load in their entirity. On the other hand, there is a whole class of algorithms that just wants to step through a file one block after another. For that, |
@bastibe: thanks for the examples To make my counter-examples a bit less hypothetical, I implemented the suggested features in #18. If you only want to read a certain part of a file, I would suggest the high-level function
or
I think that's clearer (more explicit) and more flexible (either Admittedly, this (not explicitly closing the file on read shouldn't be a problem):
... is a little less typing than
... but if you want to avoid some typing, you can use positional parameters:
... which is even one character less than the indexing solution, although I wouldn't recommend that outside of an interactive session because it will be confusing what the different numbers actually mean. As for your multi-threading example: I suspect that it is totally not safe to access the same If you are only reading, it should be perfectly safe to open the same file twice (into two different |
Oh my, I finally get what you have been saying all along. All this time, you were talking about the |
Yes, and my examples open and close the file each time. If you want to read the file in 1024-frame-chunks, you can just use the You still have to convince me that there is a situation where you want to jump around in an open file where |
When doing spectral processing, I frequently want to read consecutive, overlapping blocks of data. So the first block might be
I think it is much cleaner to do something like
|
Reading overlapping sections is indeed an interesting example! I agree that you second example is better than the first, but what about this:
Sure, this is one more line, but I think it would be more explicit, less obscure and therefore easier to read and maintain. |
I disagree. I think indexing is much easier to understand than |
As mentioned in #12, it would be nice to select certain channels by indexing.
I wanted to create a pull request, but I have still a few questions which make me think maybe it's not such a good idea after all.
Should data which was read before be somehow cached?
If a channel is requested from an interleaved file, all channels have to be read anyway, so if another channel is requested afterwards it would make sense to re-use the data.
OTOH, if only one of many channels is ever needed, the memory for all other channels will not be freed up.
Should indexing be possible when writing files?
In this case the affected frames would have to be read first, only to overwrite a part of them afterwards.
But I guess this doesn't make sense in any case ...
All-in-all, maybe the current
read()
andwrite()
methods are enough, and indexing isn't needed at all?Maybe instead, to be able to be as succinct as possible, there should be some convenience functions à la Octave's
wavread()
(to avoid explicit creation of the SoundFile object)?Because then, indexing could be used like this:
And if someone doesn't want to read the whole file, they'll have to fall back to
read()
:I guess this wouldn't be much worse than:
(Although latter may have the
__del__()
problem discussed in #13)The text was updated successfully, but these errors were encountered: