python-soundfile icon indicating copy to clipboard operation
python-soundfile copied to clipboard

Choose MP3 bitrate when writing

Open lminer opened this issue 2 years ago • 15 comments
trafficstars

Now that mp3 support has been added, it would be great to be able to choose the bitrate when writing to mp3. What is the default btw? 128?

lminer avatar May 29 '23 17:05 lminer

Does libsndfile have this feature? We can probably support it if there's an API for it.

bastibe avatar May 30 '23 15:05 bastibe

is bitrate now supported?

jimmieliu avatar Mar 27 '24 01:03 jimmieliu

Does libsndfile provide an API for it? If so, we can support it.

bastibe avatar Mar 27 '24 19:03 bastibe

Couldn't find an API so I asked here: https://github.com/libsndfile/libsndfile/issues/1008

sammlapp avatar May 07 '24 20:05 sammlapp

I don't really understand the syntax but over in that libsndfile thread 1008 evpobr linked to this documentation: https://github.com/libsndfile/libsndfile/blob/c81375f070f3c6764969a738eacded64f53a076e/docs/command.md#sfc_set_bitrate_mode

sammlapp avatar May 13 '24 11:05 sammlapp

I think that's just a flag on how the bitrate is to be interpreted. But how do we set the bitrate itself?

bastibe avatar May 14 '24 05:05 bastibe

Hm, I don't know in that case

sammlapp avatar May 20 '24 17:05 sammlapp

@bastibe more details provided by arthurt now https://github.com/libsndfile/libsndfile/issues/1008#issuecomment-2135784810

it seems like exposing the SFC_SET_COMPRESSION_LEVEL in the python-soundfile API would be useful. The argument takes values 0-1.

For VBR, it translates to lame_set_VBR_qaulity(). 0.0 -> 0.0 (highest quality), 1.0 -> 10.0 (lowest quality)

behavior is different for average and constant bitrate methods, see aurthurt's comment for details

sammlapp avatar May 30 '24 20:05 sammlapp

That sounds great! Would anyone want to prepare a pull request?

bastibe avatar May 31 '24 06:05 bastibe

I gave it a try, but did not see any effect. I first added the constant defining SFC_SET_COMPRESSION_LEVEL to soundfile_build.py:

SFC_SET_COMPRESSION_LEVEL		= 0x1301,

then running pythin setup.py install, which made this constant visible in the soundfile._snd.SFC_SET_COMPRESSION_LEVEL API.

However, with the following code, the value assigned to pointer_compression_level has no effect on the file size produced:

pointer_compression_level = _ffi.new('float *')
pointer_compression_level[0] = 0.0
with soundfile.SoundFile('./compressed.mp3','w', 44100, 1, format='MP3') as sfc:
    _snd.sf_command(sfc._file, _snd.SFC_SET_COMPRESSION_LEVEL, pointer_compression_level, _ffi.sizeof(pointer_compression_level))
    sfc.write(data) # data is numpy array of audio samples

I also tried a different syntax for setting the float value:

pointer_compression_level = _ffi.cast("float *",0.5)

but the file sizes do not change with pointer_compression_level.

I don't have any grasp on how ffi really works so I'm not sure how to proceed. I feel it would be easiest for someone more familiar with the python-soundfile library to take it from here.

I also tried with flac format and saw no difference in file size.

Documentation: https://github.com/libsndfile/libsndfile/blob/c81375f070f3c6764969a738eacded64f53a076e/docs/command.md#sfc_set_compression_level

sammlapp avatar May 31 '24 16:05 sammlapp

Thank you for looking into this. I think the pointer_compression_level should be a double, not float. What do you get as return value from _snd.sf_command? It should equal SF_TRUE or SF_FALSE.

Also, check if your version of libsndfile is new enough to support the SFC_SET_COMPRESSION_LEVEL API.

bastibe avatar Jun 02 '24 10:06 bastibe

I tried 'double', no change. The returned value is 0 (not SF_TRUE or SF_FALSE). I also updated libsndfile to 1.2.2 with brew install libsndfile, no difference.

sammlapp avatar Jun 06 '24 04:06 sammlapp

If you installed the wheel, you'll need to remove _soundfile_data from your site-packages before it'll pick up the system libsndfile. Or uninstall the wheel and install the source distribution, which does not come with _soundfile_data.

bastibe avatar Jun 06 '24 09:06 bastibe