Skip to content
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

porting 24bit wave support #94

Closed
thesunlover opened this issue Apr 8, 2015 · 19 comments
Closed

porting 24bit wave support #94

thesunlover opened this issue Apr 8, 2015 · 19 comments
Labels

Comments

@thesunlover
Copy link

According to wavio lib
https://github.com/WarrenWeckesser/wavio
there is portable 24bit support.

@jiaaro
Copy link
Owner

jiaaro commented Apr 9, 2015

It can be done as shown here and I've heard that the std lib wave module will support it too (but probably only in python 3)

@thesunlover
Copy link
Author

Well, if you send some code I can test in python 2.7
(also wavio is already running well in python2.7, i am not sure if all the functions in pydub will be supported if port from wavio is done)

@jiaaro jiaaro added the feature label Apr 16, 2015
@WarrenWeckesser
Copy link

FYI: The small wavio module that I wrote is also on pypi: https://pypi.python.org/pypi/wavio

@jiaaro
Copy link
Owner

jiaaro commented Jan 4, 2016

wavio looks like a great module - the thing that bothers me about switching from the stdlib wave module to wavio is the numpy dependency. Right now pydub doesn't require users to have a C compiler installed, which is a big hassle for less experienced developers (and even for experienced ones, it can be a source of yak shaving).

I think for users who would like to work on 24-bit wave files, I'd encourage them to convert it to 32 bit and then work on the 32 bit file in pydub. This is, admittedly, not a very elegant solution, but for casual users 24-bit wave files aren't very common, and for more sophisticated users using 32 bit audio is generally not is huge problem.

@thesunlover
Copy link
Author

Hello. I have suggestion.
Why don't combine?
If first fails we use the second.
I can provide some code we used on a project based on pydub.

@thesunlover
Copy link
Author

here is what @sg3510 used on dejavu to allow 24-bit support
worldveil/dejavu#71

@thesunlover
Copy link
Author

@WarrenWeckesser Excuse me for the ignorance, but I want to ask the question: Can we convert the code to not use the numpy module?

@jiaaro can we think of adding wavio or wavio-like option so that when we have a 24bit file we use the that option?

@WarrenWeckesser
Copy link

@thesunlover That's an old (but perfectly functional) version of the wavio module, from when it was in a gist on github. The new version (now in a github repo and on pypi) has a different API. All the versions depend on numpy.

@jiaaro I understand trying to avoid dependencies that aren't pure python. Python has been around for decades and the packaging problem still isn't completely solved. However, I've been using numpy for so long that I cringe at the thought of trying to do any nontrivial computational work in python without it.

The dependency on numpy could be removed--it's "just" a matter of writing more code. 😄

@thesunlover
Copy link
Author

@jiaaro in my experience with coding with python I have always wondered on the pre-compiled modules. These are probably C or C++ or some other kind of very optimized computational libaries.
The project I was working had to deal with computations that can reach in time from hours to days sometimes in very large projects developped by the project I worked on.

Edit:
I think that a plugin would do a very good job in this mixed up of considerations feature

Please excuse me, I will be off-topic here:
I don't say we deffinetely need this to be implemented, and I don't think we can create a poll for voting for how many ppl would need that or already had the need for that, but lets say if we have some number of cases that requires 24-bit support we can think back on that issue, what do you think?

@WarrenWeckesser
Copy link

I experimented a bit, but it looks like full support for 24 bit in pydub is not a quick fix (e.g. audioop doesn't support it). For what it's worth, here's a change that can be added to AudioSegment.__init__ that converts the data to 32 bit when a 24 bit wav file is read. The new code is between the commented dashed lines.

    ...
    else:
        # normal construction
        data = data if isinstance(data, basestring) else data.read()
        raw = wave.open(StringIO(data), 'rb')

        raw.rewind()
        self.channels = raw.getnchannels()
        self.sample_width = raw.getsampwidth()
        self.frame_rate = raw.getframerate()
        self.frame_width = self.channels * self.sample_width

        raw.rewind()

        # the "or b''" base case is a work-around for a python 3.4
        # see https://github.com/jiaaro/pydub/pull/107
        self._data = raw.readframes(float('inf')) or b''

        # -------------------------------------------------------------------------
        # Convert sample_width=3 to sample_width=4
        if self.sample_width == 3:
            # Pad each triplet of bytes with one more byte, either 0 or 0xFF.
            pad_byte = {False: '\0', True: '\xFF'}
            i = iter(self._data)
            # This conversion maintains the 24 bit values.  The values are
            # not scaled up to the 32 bit range.  Other conversions could be
            # implemented.
            self._data = ''.join(''.join(t + (pad_byte[t[-1] > '\x7f'],))
                                 for t in zip(i, i, i))
            self.sample_width = 4
            self.frame_width = self.channels * self.sample_width
        # -------------------------------------------------------------------------

    super(AudioSegment, self).__init__(*args, **kwargs)

I don't know if this is a reasonable approach for pydub, but the option might be useful for some users, especially if true 24 bit support is not going to be added soon.

@thesunlover
Copy link
Author

👍
oh, that sounds as great solution.

  • it does the job and
  • it is very simple

Can we suggest a PR in AudioSegment repository?

@thesunlover
Copy link
Author

oh, I forgot to ask if it is going to work with huge files like 2-3 hours long audio files? (I am concerned about this ;) )

@WarrenWeckesser
Copy link

What is the sample rate?

These lines should be tweaked to avoid creating full lists where possible (e.g. in Python 2, use itertools.izip instead of zip):

            i = iter(self._data)
            self._data = ''.join(''.join(t + (pad_byte[t[-1] > '\x7f'],))
                                 for t in zip(i, i, i))

@thesunlover
Copy link
Author

32bit 44100Hz if not wrong when using the 'Hz'

jiaaro added a commit that referenced this issue Jan 10, 2016
This support is based on the conversation in issue #94
@jiaaro
Copy link
Owner

jiaaro commented Jan 11, 2016

this should be working on v0.16.3 :)

@thesunlover
Copy link
Author

Sounds cool. Would love to see test on that. Thanks

@jiaaro
Copy link
Owner

jiaaro commented Jan 13, 2016

@thesunlover I'm not sure what kind of tests you mean, but I added unit tests, one of which opens a 24-bit wave file (that I exported from Logic Pro X)

@thesunlover
Copy link
Author

oh, sorry, I wrote wrong words. I already saw the tests with the 24-bit wave file. I mean that I want to run it. I would run on my Windows machine and also will look for some time to check all tests on windows as well(I saw there is an issue on windows tests)

@bobscyes
Copy link

bobscyes commented Oct 6, 2017

Hi everyone, new to pydub, my original wav file is 24-bit, use pydub to manipulate it in 32-bit, then use wavio to write to 24-bit. There is some sound distortion after conversion.

And I also try to use AudioSegment(…).set_sample_width(3), but it doesn't work.

Can anyone help? Is there any good way to convert to 24bit? Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants