0

Have been trying to create a WAV file that create a note. The reason for this is because I am trying to write a test file where I randomly generate a number of folders and sub folders containing FLAC files that I want to later modify in a certain way.

How I do it now is like this:

def sound_generation(path, freq=420, dur=5000, vol=40):
    if vol > 60 or vol < 0: raise ValueError("Set volume to a safe state.")
    a = open(path, 'wb')
    a.write(pack('>4s5L', '.snd'.encode("utf-8"), 24, 8*dur, 2, 9000, 1))
    sine_factor = 2 * pi * freq/8000
    for seg in range(8*dur):
        sine_segments = sin(seg * sine_factor)
        val = pack('b', int(vol * sine_segments))
        a.write(val)
    a.close()
    logger.info('File {} is created'.format(str(path)))

However, this create a WAV file but I want it as a FLAC, so I try to convert it like this:

def wav2flac(file_path):
    flac_path = file_path.with_suffix('.flac')
    song = AudioSegment.from_wav(file_path)
    song.export(flac_path, format = "flac")

But here I have some problems. In particular, if I do sox --i file_0.wav I get this error message

sox WARN formats_i: `file_0.wav': file header gives the total number of samples as 40000 but file length indicates the number is in fact 39976

Input File     : 'file_0.wav' (au)
Channels       : 1
Sample Rate    : 9000
Precision      : 8-bit
Duration       : 00:00:04.44 = 40000 samples ~ 333.333 CDDA sectors
File Size      : 40.0k
Bit Rate       : 72.0k
Sample Encoding: 8-bit Signed Integer PCM

So it seems like sound_generation() do not work as expected, so when I run wav2flac() it throw this error

/tmp/tmp0wsh_1_z/file_0.flac
Traceback (most recent call last):
  File "test.py", line 54, in <module>
    create_testing_folder()
  File "test.py", line 48, in create_testing_folder
    wav2flac(path)
  File "test.py", line 38, in wav2flac
    song = AudioSegment.from_wav(file_path)
  File "/home/project/venv/lib/python3.6/site-packages/pydub/audio_segment.py", line 808, in from_wav
    return cls.from_file(file, 'wav', parameters=parameters)
  File "/home/project/venv/lib/python3.6/site-packages/pydub/audio_segment.py", line 775, in from_file
    p.returncode, p_err.decode(errors='ignore') ))
pydub.exceptions.CouldntDecodeError: Decoding failed. ffmpeg returned error code: 1

Output from ffmpeg/avlib:

ffmpeg version n4.4.1 Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 11.1.0 (GCC)
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmfx --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librav1e --enable-librsvg --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-shared --enable-version3
  libavutil      56. 70.100 / 56. 70.100
  libavcodec     58.134.100 / 58.134.100
  libavformat    58. 76.100 / 58. 76.100
  libavdevice    58. 13.100 / 58. 13.100
  libavfilter     7.110.100 /  7.110.100
  libswscale      5.  9.100 /  5.  9.100
  libswresample   3.  9.100 /  3.  9.100
  libpostproc    55.  9.100 / 55.  9.100
[wav @ 0x55f93e4b3140] invalid start code .snd in RIFF header
/tmp/tmp0wsh_1_z/file_0.wav: Invalid data found when processing input

So it seems like sound_generation() is not creating a valid WAV file and because of this I can not convert it. Have tried to modify all the parameters but it still fails.

Do anyone know why? Is there a better way to just create random sound and save it as a WAV file than how I do it?

page290
  • 39
  • 5
  • Where do you write the wav header? – fdcpp Jan 23 '22 at 15:57
  • Do I not already do that in the `sound_generation()` function? – page290 Jan 23 '22 at 16:05
  • 1
    Looks like you are just using the vanilla File write. You could write the wave header manually or save yourself some trouble and use the wave module https://docs.python.org/3/library/wave.html – fdcpp Jan 23 '22 at 16:46
  • e.g https://stackoverflow.com/questions/3637350/how-to-write-stereo-wav-files-in-python/3637392#3637392 – fdcpp Jan 23 '22 at 16:46
  • That looks exactly like something I have been looking for! Thank you! – page290 Jan 23 '22 at 16:54

1 Answers1

0

Using the wave library we can achieve this by doing

def sound_generation(path, sampleRate=44100.0, duration=1.0, frequency=440.0):
    with wave.open(str(path), 'w') as f:
        f.setnchannels(1)
        f.setsampwidth(2)
        f.setframerate(sampleRate)
        for i in range(10):
            value = random.randint(-32767, 32767)
            data = struct.pack('<h', value)
            f.writeframesraw(data)

The random values can ofc be modified along with the sampling rate, duration and frequency.

page290
  • 39
  • 5