2020.06.22 波形処理 第1回 音の波と三角関数
YouTubeでポイントを説明しています。画像をクリックすると再生できます。
新シリーズとして波形処理を追加しました。波形処理を通じて、音楽に関する理解を深めることが目的です。
第1回は、音の基本となる波を、三角関数を使って作り出します。
■開発環境

パソコンから、TeraTeamでラズパイにSSH接続、python によるコーディングを行い、実行します。
また、DACにI2S接続して音を鳴らします。
DACとの接続設定は、
I2S通信によるハイレゾ音源再生
を参照してください。
ラズパイのディストリビューションには、Raspbian Stretch を使用していますが、これから導入する際には、Raspbian Buster になります。
■予備知識
まずは、こちらの論文を一読されると、理解が深まると思います。
一般の方でも読みやすく、楽しめる内容になっています。
楽典の補足資料として、またシンセサイザーに興味のある方にも十分役立つ論文です。
音の波と三角関数
小林 亮 広島大学大学院理学研究科
■波を作り出す

半径1の円周上を座標(1,0)から、反時計回りに移動した場合の軌跡を、横軸に角度(ラジアン)、縦軸に振幅(高さ,Y座標)で示すと右側の波形で表現されます。
πはラジアン単位系の表記方法と考えてください。そしてPythonのライブラリで使われる三角関数でもこの単位系が使われています。
変に2×π=2×3.1415926・・・=6.28311852・・・とか考えてしまうと訳がわからなくなります。
反時計回りに90℃回転したら、1/2π、180℃でπ、1周で2π、2周で4πという尺度で考えましょう。
また、音ってなんでこんな形をしているんだろうと考えると、謎が深まるばかりで、最終的には拒絶反応を起こしてしまいます。
これは音の実態ではなく、音の特徴を視覚的に捉えるうえで、なにかと便利なので、こういう形で表現をしていると思ってください。
■波形を表示する
では、最初にPythonでこの波形を表現してみます。
数学関数ライブラリ numpy のインストール
numpy(ナムパイ)ライブラリは、多次元配列を操作するための数学関数ライブラリです。
$ sudo pip3 install numpy
Requirement already satisfied: numpy in /usr/lib/python3/dist-packages
※Python3をインストールした際に、一緒にインストールされていると思います。
グラフ描画ライブラリ matplotlib のインストール
matplotlib(マットプロットリブ)は、NumPyのためのグラフ描画ライブラリです。
$ sudo pip3 install matplotlib
Requirement already satisfied: matplotlib in /usr/lib/python3/dist-packages
※Python3をインストールした際に、一緒にインストールされていると思います。
$ vi sinecurve.py
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
# radian値を生成(0~2πラジアンまでを、2π/360刻みで配列に格納する)
radian = np.arange(0, 2*np.pi, 2*np.pi/360)
# 振幅(Y座標)を計算
amplitude = np.sin(radian)
# 結果表示
plt.plot(radian, amplitude)
plt.show()
plt.close()
$ python3 sinecurve.py
プログラムの実行は、VNCを利用するか、ラズパイで直接行って接続しているモニターに結果を表示させてください。

■スワップ領域拡張
次に、楽器を演奏する際の音合わせにも利用される440Hzのラの音を生成して、WAVファイルに保存してみましょう。
上記では、1周期分の波の振幅を360個の観測点で採取してグラフに表しましたが、実際の録音ではより細かく観測点を設けて、振幅の値を取得しています。
例えば、ラの音をサンプリング周波数44.1kHz で録音する際には、1秒間に発生する440回の波を、44100個の観測点で採取することになり、座標計算に大量のメモリを消費します。
Raspbian Stretch の初期状態でのスワップ領域として割り当てられているスワップファイルは、100Mバイトです。
$ free
total used free shared buff/cache available
Mem: 443076 96920 152964 7596 193192 275280
Swap: 102396 0 102396
これでは計算処理中に、MemoryError を起こします。
Raspbianでは、/etc/dphys-swapfileでスワップ領域の設定を行っています。
まずは、このファイルを編集して、スワップファイルのサイズを拡張します。
$ sudo vi /etc/dphys-swapfile
#CONF_SWAPSIZE=100
CONF_SWAPSIZE=2048
サービスを起動します。
$ sudo dphys-swapfile install
want /var/swap=2048MByte, checking existing: deleting wrong size file (104857600), generating swapfile ... of 2048MBytes
スワップ領域を有効にします。
$ sudo dphys-swapfile swapon
スワップファイルが2Gバイトに拡張されます。
$ free
total used free shared buff/cache available
Mem: 443076 97484 149428 7596 196164 274688
Swap: 2097148 0 2097148
■システム・バックアップ
スワップファイルは頻繁に更新されます。SDカードには書き込み回数上限があるので、突然SDカードが使えなくなる事態を想定しなければなりません。
開発環境を1から構築しなおすのは、とても面倒なので、SDカードをバックアップしておきます。

Raspbian Stretch (あるいはBuster)をインストールした際に使用したSDカードと同じものを用意すると問題が発生しません。

■ラ(440Hz)の音を録音する
ここでは、ラ(440Hz)の音を生成して、WAVファイルに保存します。
scipy(サイパイ)ライブラリのインストール
scipy.ioにあるwavfileの読み書きクラスを使って、音声ファイル(wavファイル)を保存します。
$ sudo apt-get install python3-scipy
※scipyを、pip でインストールしようとすると、うまくいかないことがあるようです。
$ vi savewave.py
import numpy as np
from scipy.io import wavfile
if __name__ == '__main__':
frequency = 440.0 # 生成周波数
playbackTime = 1.0 # 再生時間
samplingRate = 44100 # サンプリング周波数
slice = 2*np.pi*frequency / samplingRate
radian = np.arange(0, 2*np.pi*frequency*playbackTime, slice)
amplitude = np.sin(radian)
# 16bit の wav ファイルに書き出す
amplitude = (amplitude * float(2 ** 15 - 1)).astype(np.int16)
wavfile.write("La.wav", samplingRate, amplitude)
今度は、円周上1回転分ではなく、440回転分を、等間隔に44100の観測点で振幅を測定しています。
再生時間を1秒にしていますが、単純なラの音だけの録音なので、2秒にしても同じパターンが繰り返されるだけです。
振幅を16ビットの整数値に変換している部分では、振幅を最大限に引き伸ばしていますが、音を合成する際には、調整が必要になります。
writeにパラメータを引き渡すことで、自動的にwavファイルのヘッダー情報を付加した形て保存されます。
コードを実行します。
$ python3 savewave.py
■直接、音を鳴らす
必要なパッケージをインストールします。
$ sudo pip3 install pyaudio
$ sudo apt-get install portaudio19-dev
音を再生するのに利用できるデバイスについて調べます。
$ python3
>>> import pyaudio
>>> p = pyaudio.PyAudio()
ALSAのエラーメッセージは無視して続けます。
>>> for index in range(0, p.get_device_count()):
... print(p. get_device_info_by_index(index))
...
{'maxInputChannels': 0, 'index': 2, 'defaultLowInputLatency': -1.0, 'defaultHighOutputLatency': 0.034829931972789115, 'defaultHighInputLatency': -1.0, 'defaultLowOutputLatency': 0.005804988662131519, 'name': 'snd_rpi_hifiberry_dac: - (hw:1,0)', 'defaultSampleRate': 44100.0, 'hostApi': 0, 'structVersion': 2, 'maxOutputChannels': 2}
I2S接続している PHAT DAC は、hifiberry_dac なので、インデックス番号2であることがわかります。
WAVファイルに保存していた部分を、サウンドデバイス出力用に書き換えます。
output_device_index に、上記インデックス番号の2 を指定しています。
$ vi playback.py
import pyaudio
import numpy as np
if __name__ == '__main__':
frequency = 440.0 # 生成周波数
playbackTime = 1.0 # 再生時間
samplingRate = 44100 # サンプリング周波数
slice = 2*np.pi*frequency / samplingRate
radian = np.arange(0, 2*np.pi*frequency*playbackTime, slice)
amplitude = np.sin(radian)
# 16bit の wav ファイルに書き出す
amplitude = (amplitude * float(2 ** 15 - 1)).astype(np.int16)
# ストリームを開く
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
channels=1,
rate=samplingRate,
output=True,
output_device_index=2)
# 音声を再生
stream.write(amplitude)
stream.close()
p.terminate()
$ python3 playback.py
440Hzのラの音が鳴れば、成功しています。
ALSAのエラーメッセージを表示したくない場合は、エラーハンドラーを設置します。
$ vi playback.py
from ctypes import *
import pyaudio
import numpy as np
ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
def py_error_handler(filename, line, function, err, fmt):
pass # print('%s:%s %s %s' % (line, filename, function, err))
c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)
asound = cdll.LoadLibrary('libasound.so')
if __name__ == '__main__':
# Set error handler
asound.snd_lib_error_set_handler(c_error_handler)
frequency = 440.0 # 生成周波数
playbackTime = 1.0 # 再生時間
samplingRate = 44100 # サンプリング周波数
slice = 2*np.pi*frequency / samplingRate
radian = np.arange(0, 2*np.pi*frequency*playbackTime, slice)
amplitude = np.sin(radian)
# 16bit の wav ファイルに書き出す
amplitude = (amplitude * float(2 ** 15 - 1)).astype(np.int16)
# ストリームを開く
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
channels=1,
rate=samplingRate,
output=True,
output_device_index=2)
# 音声を再生
stream.write(amplitude)
stream.close()
p.terminate()
# Reset to default error handler
asound.snd_lib_error_set_handler(None)
■参考文献
小林 亮 広島大学大学院理学研究科 - 音の波と三角関数
SciPy.org - scipy.io.wavfile.write
PythonからPyAudioで録音/再生してみる
python - PyAudioは動作しますが、毎回エラーメッセージを吐き出します
|

【深層学習関連】
【画像処理関連】

【音楽関連】

【WEBサイト構築関連】

【開発環境関連】

【SNS関連】

【周辺機器関連】

【その他】

トランジスタ技術 2021年1月号
特集: アナログ回路はノイズと闘う ~システムの性能を維持して安定な動作を実現するために~
Interface 2021年1月号
☆特集 Jetson/ラズパイ/PCで自習 Python画像処理100
☆特別付録:コンピュータ手帳2021
日経Linux 2021年 1月号
★超保存版・冊子付録 Ubuntu完全対応 Linuxコマンド逆引き大辞典 264項目
★付録DVD 特集連動2本入り「Ubuntu 20.10 日本語Remix」「Ubuntu Server20.10」
ラズパイマガジン2020年12月号
温度、距離、におい、圧力など、さまざまな種類のセンサー350種類を一挙に紹介します。特性や価格を示した一覧表を用意したので、用途に合った適切な製品を選べます。そのうちの34種類のセンサーは、仕組みから配線図まで図解で分かりやすく解説します。
15Stepで踏破 自然言語処理アプリケーション開発入門
エンジニアの実務に役立つ知識に絞り、独自に15の学習ステップを体系化しました。
数値計算にNumPy、形態素解析にMeCab、機械学習にscikit-learn、ディープラーニングに
Keras等を使い、Pythonのコードを記述し動かしていきます。
プログラミング・ビットコイン ―ゼロからビットコインをプログラムする方法
Linuxサーバーがゼロから作れる本
このLinuxを使いこなす上で一番手っ取り早いのが自分でLinuxサーバーを構築してみることです。
WindowsやMacのパソコンしか使ったことが無い人でも理解できるよう、
しくみや手順の解説を丁寧にまとめ上げた、ゼロからのサーバー入門ガイドです。
Raspberry Pi 3 Model B V1.2 (日本製) 国内正規代理店品
【仕様概要】CPU:ARM 1.2GHz 4コア、GPU:2コア 3D・動画支援、RAM:1GB、ネットワーク:LAN/Wi-Fi/Bluetooth、インターフェース:USB/HDMI/オーディオ/GPIO(UART/I2C/I2S/SPI...)。
Arduino Nano
ATmega328搭載/
動作電圧: 5V/
入力電源電圧(推奨):7~12V/
デジタル入出力ピン: 14本/
PWMチャンネル: 6本/
アナログ入力チャンネル: 8本/
直流電流(1ピン当り最大): 40 mA/
直流電流(3.3Vピン、1ピン当り最大): 50 mA/
Flashメモリ: 32 KB (ATmega328) 内2KBはブートローダーで使用/
SRAM: 2 KB (ATmega328)/
EEPROM: 1 KB (ATmega328)/
Clock Speed: 16 MHz
逆引き PIC電子工作 やりたいこと事典
機能が豊富で、速度・アナログ制御・省電力性・コストの面でもアドバンテージをもつPICマイコン。そんなPICマイコンの使い方を、目的別にやりたいことから引ける、逆引きタイプのガイドブックです。
C言語による PICプログラミング大全
2002年に初版、2009年に第2版を発売した名著『C言語によるPICプログラミング入門』
が大幅リニューアルし「大全」として生まれ変わりました。
本書では、機能豊富なPIC16F1シリーズを使いこなすために、統合開発環境を
MPLAB X IDEに、CコンパイラはMicrochip Technology社純正のXC8に、それぞれ変更しました。
C言語でPICマイコンのプログラミングを始めたい方から、最新のPICマイコンの機能をとことん使い倒したい方まで、必ず役に立つ1冊です。
PICと楽しむRaspberry Pi活用ガイドブック
「PICマイコン+Raspberry Pi3B」という組み合わせで、高機能な電子工作を簡単に実現し、電子工作を各段に高度化する方法について解説していきます。
ESP32&Arduino 電子工作 プログラミング入門
電子工作ファンに人気のマイコンArduino、そしてWiFiとBluetooth内蔵でネットワーク接続しやすいESP32。それらのマイコンでプログラムを組む際に使うのが「Arduino言語」です。
超特急Web接続!ESPマイコン・プログラム全集
IoT技術の回路とプログラムを解説しました.
トランジスタ技術2016年9月号と2017年3月号の特集に
最新の情報を加筆して一冊に仕上げました.
回路とプログラムのサンプル資料として最適です.
ラズベリー・パイやIchigoJamを連動させた例も紹介しています
M5Stack用カード型キーボードユニット
M5Stackにフル機能のQWERTY配列キーボードを実装できるユニットです。複数のボタンの組み合わせ(Sym + Key、Shift + Key、Fn + Key)や豊富なキーの値を出力することが可能です。
Ubuntu サーバー徹底構築
サーバー用UbuntuでLinuxサーバーを構築しよう!
導入からLinuxやコマンドの基本、各種サーバー構築、バックアップやストレージ管理まで!
サーバー用Linuxディストリビューションとして定評のあるUbuntu Serverの中でも、
10年長期サポート版であるUbuntu Server 18.04 LTSに対応!
[改訂第3版]Linuxコマンドポケットリファレンス
本書はLinux操作に必要なコマンドを収録したポケットリファレンスです。機能別にコマンドを分類し、各コマンドページでは書式/使用例などをコンパクトにまとめています。またアルファベット順索引も用意しており、名前しかわからなくてもすぐに目的のコマンドを探すことができます。今回の改訂では仮想化、データベース、クラウド時代に対応したネットワークコマンドなどを追加しています。おもなLinuxディストリビューションのCentOS、Fedora、Debian GNU/Linux、Ubuntuに対応し、初心者から上級者まで必携の1冊です。
できるPRO Apache Webサーバー 改訂版 Version 2.4/2.2/2.0対応
番のApache独学書を改訂しました!
CentOS、Ubuntu、Windows、Mac OS Xに対応しています。できるPROシリーズは、実際の画面や詳細なイラスト、概念図などで構成。
はじめての方でも理解しやすくなっています。
インストール、アクセス制限、CGI、モジュール拡張、ログ管理など、基本的なことから実践的なことまでていねいに解説しています。
[改訂第3版]PHPポケットリファレンス
PHPを利用したいすべての方必携の「PHPポケットリファレンス」最新版がついに登場! PHP 5/4による開発の際によく利用される機能を集約し、必要な知識を目的別、逆引きでまとめました。PHP5.3以降を対象とし、PHP4からある機能はPHP4でも利用できることがわかるようになっています。またオブジェクト指向型のAPI解説を大幅に強化。開発の現場には1冊置いておきたい書籍です。
MySQL ポケットリファレンス
MySQLはさまざまなWebサービスの中核を担うデータベースです。本書はMySQLの基礎的な内容を中心に、日常的によく使うちょっとしたコマンドや、外部管理ツールとの連携など、MySQLの管理/運用にあたって便利な情報を素早く探し出すことができます。MySQL自体の操作、MySQL特有のコマンド、MySQL専用管理ツール、PHPからの操作など、MySQLを実際に使っているユーザーに役立つ内容となっています。
Postfix詳解―MTAの理解とメールサーバの構築・運用
電子メールの配送システムの中核を担うプログラム「MTA」(Message Transfer Agent)のひとつが、「Postfix」です。 この全容を記した本です。
すところなく解説していきます。
DNSがよくわかる教科書
本書では、DNSの仕組みから、ドメイン名のルール、主なリソースレコードの内容、コマンドによる動作確認、DNSの運用ノウハウ、DNSSECの基礎知識まで、順を追ってやさしく解説します。
|