python3でwavファイルを読んだり書いたり

wavファイルのformatを調べながら読んだり書いたりしてみた


wavファイルのformatはこちらのサイトで調べた

wav format

wav read

適当なwavファイルを読んでみた

readしたwavのformat記述をprintする


        """ read sample sin wav """
        #
        # sample sine wav file
        # audiocheck.net_sin_1000Hz_-3dBFS_0.01s.wav
        #
        #

        import os
        import struct

        BASEDIR = os.path.dirname(__file__) + '\\'
        FILENAME = 'audiocheck.net_sin_1000Hz_-3dBFS_0.01s.wav'
        # file size
        STATINFO = os.stat(BASEDIR + FILENAME)
        print(FILENAME)
        print(STATINFO)
        print('size: ', STATINFO.st_size)
        print('-' * 10)
        print('wav header')
        print('-' * 10)
        with open(BASEDIR + FILENAME, 'rb') as f:
            RIFF = f.read(4)
            print('CHUNK ID(4): ', RIFF.decode('utf-8'))
            CHANKBYTES = f.read(4)
            CHUNKSIZE = struct.unpack('<L', CHANKBYTES)     # little endian 4byte to Long(4byte)
            print('CHUNK SIZE(4): ', CHUNKSIZE[0])
            FORMAT = f.read(4)
            print('FORMAT(4): ', FORMAT.decode('utf-8'))
            print('*' * 50)
            SUBCHANK1ID = f.read(4)
            print('SUBCHANK1ID(4): ', SUBCHANK1ID.decode('utf-8'))  # 'fmt '
            SUBCHANKSIZEBYTES = f.read(4)
            SUBCHANKSIZE = struct.unpack('<L', SUBCHANKSIZEBYTES)
            print('SUBCHANKSIZE(4): ', SUBCHANKSIZE[0])
            AUDIOFORMATBYTES = f.read(2)
            AUDIOFORMAT = struct.unpack('<H', AUDIOFORMATBYTES)
            print('AUDIOFORMAT(2): ', AUDIOFORMAT[0])           # 1: PCM / other : compressed
            NUMCHANNELSBYTES = f.read(2)
            NUMCHANNELS = struct.unpack('<H', NUMCHANNELSBYTES)
            print('NUMCHANNELS(2): ', NUMCHANNELS[0])
            SAMPLELATEBYTES = f.read(4)
            SAMPLELATE = struct.unpack('<L', SAMPLELATEBYTES)
            print('SAMPLELATE(4): ', SAMPLELATE[0])
            BYTELATEBYTES = f.read(4)
            BYTELATE = struct.unpack(''lt;L', BYTELATEBYTES)
            print('BYTELATE(4): ', BYTELATE[0])
            BLOCKALIGNBYTES = f.read(2)
            BLOCKALIGN = struct.unpack('<H', BLOCKALIGNBYTES)
            print('BLOCKALIGN(2): ', BLOCKALIGN[0])
            BITSPERSAMPLEBYTES = f.read(2)
            BITSPERSAMPLE = struct.unpack('<H', BITSPERSAMPLEBYTES)
            print('BITSPERSAMPLE(2): ', BITSPERSAMPLE[0])
            print('*' * 50)
            SUBCHUNK2ID = f.read(4)
            print('SUBCHUNK2ID(4): ', SUBCHUNK2ID.decode('utf-8'))  # 'data'
            SUBCHUNK2SIZEBYTES = f.read(4)
            SUBCHUNK2SIZE = struct.unpack('<L', SUBCHUNK2SIZEBYTES)
            print('SUBCHUNK2SIZE(4): ', SUBCHUNK2SIZE[0])

      

wav write

8bit/8000/mono/のデータを書き込む

上のread pgで読み込んで確認しながら作成

データ用にrbin.binというファイル名で7fff個のデータをバイナリで作成しておいた


        ''' gen wav file'''
        #! coding: utf-8

        #
        # generate wav file from raw data
        # 8bit/8kHz wav data
        #
        #

        import os

        BASEDIR = os.path.dirname(__file__) + '\\'

        #
        # wav header parms
        # value 0 is set in pg
        #
        WAVHEADER = {
            'chunkid' : 'RIFF',
            'chunksize' : 0,
            'format' : 'WAVE',
            'subchunk1id' : 'fmt ',
            'subchunk1size' : 16,
            'audioformat' : 1,
            'numchannels' : 1,
            'samplerate' : 4000,
            'byterate' : 0,
            'blockalign' : 0,
            'bitspersample' : 8,
            'subchunk2id' : 'data',
            'subchunk2size' : 0
        }

        FILENAME = 'rbin.bin'
        STATINFO = os.stat(BASEDIR + FILENAME)
        print('rbin.bin')
        print(STATINFO)
        FSIZE = STATINFO.st_size
        print('size: ', FSIZE)

        # size data set
        WAVHEADER['chunksize'] = FSIZE + 36
        WAVHEADER['subchunk2size'] = FSIZE
        print(WAVHEADER['subchunk2size'].to_bytes(4, 'little'))
        # calc params
        NUMCHANNELS = WAVHEADER['numchannels']
        SAMPLERATE = WAVHEADER['samplerate']
        BITSPERSAMPLE = WAVHEADER['bitspersample']
        WAVHEADER['byterate'] = SAMPLERATE * NUMCHANNELS * BITSPERSAMPLE // 8
        WAVHEADER['blockalign'] = NUMCHANNELS * BITSPERSAMPLE // 8
        # bytes data
        WAVS = bytes(WAVHEADER['chunkid'], 'utf-8')
        WAVS += WAVHEADER['chunksize'].to_bytes(4, 'little')
        WAVS += bytes(WAVHEADER['format'], 'utf-8')
        WAVS += bytes(WAVHEADER['subchunk1id'], 'utf-8')
        WAVS += WAVHEADER['subchunk1size'].to_bytes(4, 'little')
        WAVS += WAVHEADER['audioformat'].to_bytes(2, 'little')
        WAVS += WAVHEADER['numchannels'].to_bytes(2, 'little')
        WAVS += WAVHEADER['samplerate'].to_bytes(4, 'little')
        WAVS += WAVHEADER['byterate'].to_bytes(4, 'little')
        WAVS += WAVHEADER['blockalign'].to_bytes(2, 'little')
        WAVS += WAVHEADER['bitspersample'].to_bytes(2, 'little')
        WAVS += bytes(WAVHEADER['subchunk2id'], 'utf-8')
        WAVS += WAVHEADER['subchunk2size'].to_bytes(4, 'little')
        #print(WAVS)
        with open(BASEDIR + FILENAME, 'rb') as f:
            WAVS += f.read()
        with open(BASEDIR + 'x.wav', 'wb') as f:
            f.write(WAVS)



      

読み込んだバイナリデータをbitreverseする場合

format書込み後、datファイル読み込み部以降を下のようにする


        .....
        RAWS = bytes()
        with open(BASEDIR + FILENAME, 'rb') as f:
            RAWS = f.read()
        for d in RAWS:
            r = int('{0:08b}'.format(d)[::-1], 2)
            WAVS += r.to_bytes(1, 'little')
        with open(BASEDIR + 'xreverse.wav', 'wb') as f:
            f.write(WAVS)
      

作成したwavファイルはwindows media playerで再生できた。

鳴らしてみたものの、用意したデータがwavではなく、adpcmか何かのようだ、、、