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

Cannot write Ogg files over 96 seconds long at 44.1 kHz

Open carlthome opened this issue 1 year ago • 4 comments
trafficstars

Not entirely sure how this happens, but I've been observing program crashes with sf.write for any Ogg file over a duration of 95-96 seconds at 44.1 kHz.

This works:

sf.write("audio.ogg", np.zeros((44100*95, 2)), 44100)

While this crashes:

sf.write("audio.ogg", np.zeros((44100*96, 2)), 44100)

on 0.12.1 macOS M1, 32 GB RAM.

carlthome avatar Jan 31 '24 13:01 carlthome

Thank you for the bug report.

How did you install soundfile? Is there an error message?

bastibe avatar Feb 01 '24 06:02 bastibe

I've done pipenv install librosa and got

librosa==0.10.1
  - audioread [required: >=2.1.9, installed: 3.0.1]
  - decorator [required: >=4.3.0, installed: 5.1.1]
  - joblib [required: >=0.14, installed: 1.3.2]
  - lazy-loader [required: >=0.1, installed: 0.3]
  - msgpack [required: >=1.0, installed: 1.0.7]
  - numba [required: >=0.51.0, installed: 0.59.0]
    - llvmlite [required: >=0.42.0dev0,<0.43, installed: 0.42.0]
    - numpy [required: >=1.22,<1.27, installed: 1.26.3]
  - numpy [required: >=1.20.3,!=1.22.2,!=1.22.1,!=1.22.0, installed: 1.26.3]
  - pooch [required: >=1.0, installed: 1.8.0]
    - packaging [required: >=20.0, installed: 23.2]
    - platformdirs [required: >=2.5.0, installed: 4.2.0]
    - requests [required: >=2.19.0, installed: 2.31.0]
      - certifi [required: >=2017.4.17, installed: 2023.11.17]
      - charset-normalizer [required: >=2,<4, installed: 3.3.2]
      - idna [required: >=2.5,<4, installed: 3.6]
      - urllib3 [required: >=1.21.1,<3, installed: 2.2.0]
  - scikit-learn [required: >=0.20.0, installed: 1.4.0]
    - joblib [required: >=1.2.0, installed: 1.3.2]
    - numpy [required: >=1.19.5,<2.0, installed: 1.26.3]
    - scipy [required: >=1.6.0, installed: 1.12.0]
      - numpy [required: >=1.22.4,<1.29.0, installed: 1.26.3]
    - threadpoolctl [required: >=2.0.0, installed: 3.2.0]
  - scipy [required: >=1.2.0, installed: 1.12.0]
    - numpy [required: >=1.22.4,<1.29.0, installed: 1.26.3]
  - soundfile [required: >=0.12.1, installed: 0.12.1]
    - cffi [required: >=1.0, installed: 1.16.0]
      - pycparser [required: Any, installed: 2.21]
  - soxr [required: >=0.3.2, installed: 0.3.7]
    - numpy [required: Any, installed: 1.26.3]
  - typing-extensions [required: >=4.1.1, installed: 4.9.0]

No error message that I can see, but perhaps it's librosa that misses a transitive dependency for soundfile?

carlthome avatar Feb 01 '24 10:02 carlthome

Thank you. This is probably an issue with upstream libsndfile.

You will need to check with them if they have a fix for this issue. They may already have fixed it actually, as soundfile is one version behind libsndfile at the moment.

bastibe avatar Feb 02 '24 13:02 bastibe

I ran into this issue, and after looking around a bit it seems that this limitation has existed since at least 2014. One workaround that I discovered from a GNU Octave bug report is to write the file out in chunks of size 2^20 instead of writing it out all at once with sf.write. So, I wrote this write_chunked function that can be used as an alternative for sf.write:

def write_chunked(file, data, samplerate, subtype=None, endian=None, format=None,
          closefd=True, chunk_size=0x100000):
    import numpy as np
    data = np.asarray(data)
    if data.ndim == 1:
        channels = 1
    else:
        channels = data.shape[1]
    with SoundFile(file, 'w', samplerate, channels,
                   subtype, endian, format, closefd) as f:
        num_chunks = (len(data) + chunk_size - 1) // chunk_size
        for chunk in np.array_split(data, num_chunks, axis=0):
            f.write(chunk)

From my limited testing it seems to work fine for writing vorbis files.

dernett avatar Jun 05 '24 20:06 dernett