ぽきたに 〜ありきたりな非凡〜

現役F欄大学生が送るゴミ溜めと独り言

【Python】WAVファイルを等間隔に分割するプログラムpart2【サウンドプログラミング】

どうも、たっきーです。

今回は前回の続き。

 

 

なにする?

前回のヤァツの強化版作りたい。

前回のヤァツはファイル一個に対してしか分割できなかったけど、今回は複数ファイルを一括で等間隔で分割したい。

 

前回

tacky0612.hatenablog.com

 

環境

  • numpy 1.13.3
  • scipy 0.19-.1

 

下準備

f:id:tacky0612:20171124154839p:plain

とりあえず等間隔に分割したいWAVファイルを0〜n.wavというファイル名で用意する。(nはファイル数-1)

データ数が100ぐらいならいいけど、それより多くなると面倒くさいので自動で0〜nで名前をふれる方法があれば教えて欲しいでござる…。

  

コード

import wave
import struct
import math
import os
from scipy import fromstring, int16

# 一応既に同じ名前のディレクトリがないか確認。
file = os.path.exists("output")
print(file)

if file == False:
    #保存先のディレクトリの作成
    os.mkdir("output")

def cut_wav(filename,time,start):  # WAVファイルを刈り奪る 形をしてるだろ? 
    # timeの単位は[sec]

    # ファイルを読み出し
    wavf = str(filename) + '.wav'
    wr = wave.open(wavf, 'r')

    # waveファイルが持つ性質を取得
    ch = wr.getnchannels()
    width = wr.getsampwidth()
    fr = wr.getframerate()
    fn = wr.getnframes()
    total_time = 1.0 * fn / fr
    integer = math.floor(total_time) # 小数点以下切り捨て
    t = int(time)  # 秒数[sec]
    frames = int(ch * fr * t)
    num_cut = int(integer//t)

    # 確認用
#     print("Channel: ", ch)
#     print("Sample width: ", width)
#     print("Frame Rate: ", fr)
    print("Frame num: ", fn)
#     print("Params: ", wr.getparams())
    print("Total time: ", total_time ,"sec")
#     print("Total time(integer)",integer)
#     print("Time: ", t) 
#     print("Frames: ", frames) 
    print("Number of cut: ",num_cut)

    # waveの実データを取得し、数値化
    data = wr.readframes(wr.getnframes())
    wr.close()
    X = fromstring(data, dtype=int16)
#     print(X)


    for i in range(num_cut):
#         print(i)
        # 出力データを生成
        outf = 'output/' + str(i+start) + '.wav' 
        start_cut = i*frames
        end_cut = i*frames + frames
#         print(start_cut)
#         print(end_cut)
        Y = X[start_cut:end_cut]
        outd = struct.pack("h" * len(Y), *Y)

        # 書き出し
        ww = wave.open(outf, 'w')
        ww.setnchannels(ch)
        ww.setsampwidth(width)
        ww.setframerate(fr)
        ww.writeframes(outd)
        ww.close()
        
    return i+start+1 # 現在のカット済のファイル名の次を返す(はず)

n = 0
print("cut time = ")
cut_time = input()
print("Number of file = ")
a = input()
num_file = int(a)+1
print('=====================================================')
for name_file in range(int(num_file)):
    print("name_file : ",name_file,".wav")
    n = cut_wav(name_file,cut_time,n)
    print('return :',n)
    print('=====================================================')

 

前回書いたコードをちょっと手入れした。(ちょっと汚いコードなのは性格。)

cut_wav()をちょっと変更して、

  • returnでカット済のファイル名の次の値を返す
  • 始まりのファイル名を引数に追加

あとは、for文でcut_wav()を回してるだけ。 

分割したい時間と最後のファイル名(ファイル数-1)を指定できるようにしてある。

 

このコードをデータセットを同じディレクトリ内に保存する。

f:id:tacky0612:20171124163415p:plain

あとはターミナルで以下コマンド叩くだけ。

$ cd データセットとこのコードが入ってるディレクトリへのPath

$ python コード名(この場合cut_wav).py

 ってやると、分割したい時間と最後のファイル名(ファイル数-1)の入力を求められるので入力する。今回は1秒毎に分割したくて最後のファイル名が87.wavなので、cut_timeには1、Number of fileには87を入力する。

f:id:tacky0612:20171124164818p:plain

 こんな感じ。

   ↓ 終点 ↓

f:id:tacky0612:20171124164905p:plain

 最後のreturn(今回は1900)が分割後のファイル数になる。

同じディレクトリ内にoutputってディレクトリが生成され、その中に分割後のWAVファイルが格納されるようになっている。

f:id:tacky0612:20171124165215p:plain

 ※returnが1900なのに生成された最後のWAVファイルが1899なのは0〜1899で1900個であるため。(return に+1している為でもある。)

 

上手く分割出来た✌

 

退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

 
サウンドプログラミング入門――音響合成の基本とC言語による実装 (Software Design plus)

サウンドプログラミング入門――音響合成の基本とC言語による実装 (Software Design plus)

 

 

おわりに・感想

88個のWAVファイルを分割することで1900個のWAVファイルに増やすこと(いや、増えてはいないが)が出来た。

考えられる問題点は、1秒で分割したので1秒間が全部無音とかが存在しそうってことかな。(検証してないのでわからん)

そういうのがあったら機械学習やる上で不都合なのでどうにかして除去したい。

今日はこんなくらいで、さよならー。

 

 

 

スポンサードリンク