(^p^)ブログ

いろいろなことがかかれていきます 編入関連の質問はTwitter,@mast15yamachiにて

(^p^)のーと:2/1 pythonで音関連ファイルをあれこれするまとめ

28日チャレンジ1日目は音データの扱いについて書きます。

何番煎じかはわかりませんが、これから音データを処理するにあたり、そもそもファイルを扱えるようにしないといけないな、と思って書いてみます。

 

ほとんどそれぞれのモジュールの基本的なところしか触っていませんが、まあ最初だし、ネタがまだ思いついてないし、今後よく使うだろうねってことで備忘録もかねてやっておきます。

 

音声ファイル

まず、音を音波そのものとして記録する音声ファイルの扱いから。

wav,mp3,aacといったファイルをいろいろやる方法についてまとめてみる。

 

・古くからの方法

自分はこれまでこの方法しか知らなかったので、書きます。

これは古くから伝わる(?)wavファイルの入出力方法です。

wavファイルの取り扱いは、python標準ライブラリのwaveモジュールを使います。

また、そのデータを再生したり録音したりするには、pyaudioというモジュールを使います。

people.csail.mit.edu

 

 

さっそくやってみましょう。

・音声ファイルの読み込み&再生

import wave
import pyaudio

# 音声ファイルを読み込み再生する
CHUNK = 1024
# test.wavを読み込みモードで開く
with wave.open("test.wav","rb") as wf:

# test.wavを再生
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),#ストリームを読み書きするときのデータ型
channels = wf.getnchannels(),#モノラルかステレオか 1でモノラル2でステレオ
rate = wf.getframerate(),#サンプリング周波数
output=True)#出力モード

data = wf.readframes(CHUNK)

while data != '':
stream.write(data)#ストリームに書き込み
data = wf.readframes(CHUNK)#次のデータを読み込む

stream.stop_stream()
stream.close()
p.terminate()

このプログラムを実行するとtest.wavが再生されます。

 

・音声を録音してwavファイルへ書き込む

import pyaudio
import wave

CHUNK = 1024

#int16型
FORMAT = pyaudio.paInt16

#ステレオ
CHANNELS = 2

#サンプリング周波数44100Hz
RATE = 44100

#5秒間録音
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "hogehoge.wav"

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)

print("* recording")

frames = []

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)

print("* done recording")

stream.stop_stream()
stream.close()
p.terminate()

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

これでhogehoge.wavという名前の音声ファイルとして5秒間の録音ができます。

 

pyaudioはリアルタイム性に優れたところがあり、スペクトルアナライザとか作れるみたいなので、いつの日か試してみたいですね。

 

ただ、この長さを書くのは正直めんどくせー・・・

再生するのにいちいちチャンネルとかチャンク数とかこっちが書くのかよ。

 

っておもってたら、こんなモジュールを発見しました。

jiaaro/pydub @ GitHub

pydubという最近(といっても4年前)リリースされた、音声ファイルを楽にpythonで再生できるモジュールです。

音声ファイルを再生するなら・・・

import pydub
from pydub import AudioSegment
from pydub.playback import play

song = AudioSegment.from_wav("test.wav")

play(song)

らくちん。ストリームどうこうしなくても楽に書けます。

このpydub、公式ドキュメントを読みつくしてないのですが、

どうやら音声を合成したり、ファイルフォーマットの変換もできるみたいです。

 

楽譜ファイル

音の中でも、構造化された音楽を楽譜として保存する形式。

MIDIが特に有名ですが、MusicXmlなんていうXml形式のフォーマットもあります。

https://ja.wikipedia.org/wiki/MusicXML

タグが音の高さだったり長さだったりする形式のXMLです。

 

Midiファイルを扱うモジュールとしてはmidoかpretty-midiが有名ですかね。

Mido - MIDI Objects for Python — Mido 1.2.8 documentation

pretty_midi — pretty_midi 0.2.8 documentation

 

私は春の実験の最終課題として自動作曲*1をやったのですが、その際に使ったのはpretty-midiなので、今回そっちをつかってやってみます。

 

Midiファイルを読み込み、いじる

import pretty_midi

#Midiファイルの読み込み
midi_data = pretty_midi.PrettyMIDI('test.mid')

#ドラム以外の楽器の音を半音上げる
for instrument in midi_data.instruments:
if not instrument.is_drum:
for note in instrument.notes:
note.pitch += 1
#このデータを新たなmidiファイルに書き込み
midi_data.write("pitch_up_test.mid")

・任意の音でMIDIをつくる

#midiファイルの生成
cello_c_chord = pretty_midi.PrettyMIDI()
#チェロの音色で
cello_program = pretty_midi.instrument_name_to_program('Cello')
cello = pretty_midi.Instrument(program=cello_program)
# ド・ミ・ソの和音
for note_name in ['C5', 'E5', 'G5']:
note_number = pretty_midi.note_name_to_number(note_name)
#ヴェロシティ(音量)を100、0.5秒間鳴らす
note = pretty_midi.Note(
velocity=100, pitch=note_number, start=0, end=.5)
cello.notes.append(note)
cello_c_chord.instruments.append(cello)
#cello-C-chord.midというファイルを生成
cello_c_chord.write('cello-C-chord.mid')

こんな感じでMIDIファイルを自由自在に扱うことができます。

 

midiの再生もpythonでやりてえよ、って人はこのリンク先のコードを試してみればいいんじゃないかと思います(筆者は未検討))

www.daniweb.com

また、midiを分析するmusic21というモジュールもあります。

music21: a Toolkit for Computer-Aided Musicology

使用例については、2月の第1週のどこかで、

僕の春の実験でやったことをもう一回再現しながらやりたいと思います。

 

 

今回は音関連ファイルを処理するpythonのモジュールを紹介してきました。

こんな感じでゆるゆる~っと音処理について毎日いろいろ書いてこうと思います。

 

 

次はなにかものを実際に作ってみようかな。

 

とりあえず溜まってるネタ

  • 沖縄風JPOPを解析しよう(music21、実験でやった)
  • リアルタイムサウンドスペクトルアナライザ
  • 鼻歌認識
  • 音源分離
  • 音関連APIをたたいてみよう
  • 自動作曲再チャレンジ

などなど・・・

 

・・・忙しい2月になりそうだ(|||^p^)

 

 

*1:遺伝的アルゴリズムを使った。曲ではないなにかが生成された