はじめに
ここではPCで使われている音声ファイル形式のwavファイルのデータをA33Fで再生してみます。このページは難易度が急に上がりますので注意して下さい。
※このページで紹介する内容はあくまでも一例です。個別の作成のご相談ご質問はお答えできませんのでご了承下さい。このページと同じ内容についてのご質問についてはロボット掲示板にてお願いいたします。
※以下の情報は2007年12月現在のものです。ご注意ください。
※このページではC言語の基本的な部分を理解している方向けに書いてあります。また、何回かMPLABの操作を行った方を対象にしています。それ以外の方はまず基本編を読んで下さい。
wavファイルについて
PCで音声をあつかう場合にはいろいろなファイル形式があります。その中で、wav(ウェブ)ファイルというものが、リニアPCM方式でデータを扱うことができます。つまり、A33FのPCMに近い形式のものがあります。
wavファイルをインターネットで検索するとどのようなフォーマットかがわかります。
フォーマットは次のようになっているようです。
名称 |
Size
(byte) |
説明 |
例 |
RIFFヘッダ |
4 |
|
'R' 'I' 'F' 'F' |
ファイルサイズ |
4 |
これ以降のファイルサイズ (ファイルサイズ - 8) |
|
WAVEヘッダ |
4 |
RIFFの種類がWAVEであることをあらわす |
'W' 'A' 'V' 'E' |
fmt チャンク |
4 |
フォーマットの定義 |
'f' 'm' 't' ' ' (←スペースも含む) |
fmt チャンクのバイト数 |
4 |
バイト数 |
リニアPCM ならば 16(10 00 00 00) |
フォーマットID |
2 |
フォーマットID |
リニアPCM ならば 1(01 00) |
チャンネル数 |
2 |
チャンネル数 |
モノラル ならば 1(01 00)
ステレオ ならば 2(02 00) |
サンプリングレート(Hz) |
4 |
サンプリングレート |
44.1kHz ならば 44100(44 AC 00 00) |
データ速度 |
4 |
(Byte/sec) |
44.1kHz 16bit ステレオ ならば
44100×2×2 = 176400(10 B1 02 00) |
ブロックサイズ |
2 |
(Byte/sample×チャンネル数) |
16bit ステレオ ならば
2×2 = 4(04 00) |
サンプルあたりのビット数 |
2 |
(bit/sample) |
16bit ならば 16(10 00) |
拡張部分のサイズ |
2 |
|
|
拡張部分 |
n |
|
|
data チャンク |
4 |
|
'd' 'a' 't' 'a' |
波形データのバイト数 |
4 |
バイト数n |
|
波形データ |
n |
|
|
このフォーマットを見ると、単純に先頭の数バイトを除いた部分が音声のPCMデータになっているようです(dataチャンク以降の部分)。
PCの音源などは、サンプリングレートが44.1kHzのものが多いようです。ビット数は16bitが多いようです。波形データは16bitの場合はリトルエンディアン(下位バイトが先になる)のようです。
A33Fの音声出力は「サンプリングレートが8kHzの16ビットPCM」なので、PCで使われているwavファイルを8kHzのサンプリングレートに落として、波形データだけ抽出できればA33Fでも再生することが可能と思われます(実際、以降で実験した結果、可能でした。)。
wavファイルネタ
A33Fはロボット作成を想定しているボードなので、音声を出すことを考えます。wavファイルの音声はインターネットでフリーの音源が入手できますが、今回は「あみ声」を使ってみました。プロの声優の方が、PCのシステムボイスやゲームにつかえそうな音声を録音しており、ベクターなどでフリーで入手できます。今回は「あみ声システムボイス集オフィスバージョン」をダウンロードしました。
ファイルを回答すると、次のように.wavの拡張子が付いた音声データが出ます。
※フリーの音声データの入手は各自の責任で行ってください。
wavファイルのサンプリングレートなどの変換について
上記で入手した音声は、やはりサンプリングレートが8kHzではなかったので、フリーの変換ソフトを探してみました。「wavファイル 形式変換」あたりのキーワードでグーグルすると、フリーのSCMPXというフリーウェアのMP3プレーヤソフトでwavファイルのサンプリングレート変換ができるということがわかりましたのでさっそく実行してみます。
尚、この記事は2007年12月現在の情報なので、SCMPXが見当たらない場合は各自フリーソフトなどを探してみてください。
SCMPXをダウンロードして解等すると、フォルダの中は次のようになります。この中のSCMPX.exeが実行ファイルで、これだけで動くようです(インストールなど不要)。
SCMPXを起動すると次のような画面が開きます。
データを変換するには「CONVERT」->「Single file」 ->「Resample」を押し、その後の指示に従ってファイルを指定します。
先にダウンロードしたあみ声の 02_error.wav ファイルを開いたところです。
これを見ると、サンプリングレートは22050Hzのようです。ビットは16bit、チャンネルはモノラルなので問題ありません。ということでサンプルレートを8000に変更して「OK」を押して変換します。同じ名前にすると上書きされてしまうので、ここではとりあえず
02_error_rs_8000.wav という名前で保存しました。
ということで、このファイルから音声データだけを抽出できればよいことになります。
音声データの受け渡し
PC上のデータをA33Fへ渡す方法ですが、これはフリーソフトなどはなく、自分で作るしかありません。浅草ギ研では以前から別のマイコンボードとの連携方法として、MicroSoftのVisualStudio2005でのPCアプリの作成について説明してきました。ということで、今回は簡単にVS2005のC#でwavファイルをA33Fへダウンロードするソフトを作ってみました。
wavファイルダウンロードソフトウェア
2007年12月現在で、すでに開発環境はVS2005からVS2008へ移行しそうな気配ですが、とりあえず今回は2005で作ってみます。VS2005ではExpressEditionというフリーのバージョンもマイクロソフトから入手できます。これらの様子はこちらの「VisualC#2005ExpressEditionを使ってみる」に書いてあります。
また、A33Fとはシリアル通信でデータをやりとりしますが、C#2005でシリアル通信のプログラムを作る様子は「VisualC#2005のシリアル通信機能を使ってみる」に書いてあります。
尚、これらを使うには、.Net FreamWorks Ver2.0 以上が入っていないと動きませんので注意して下さい。
ということで作ったソフトがこちらになります。(プロジェクト全体が圧縮されてますので解等して下さい。右クリックで対象を保存)
PcmToA33F.lzh
こまかいところはForm1.csのコメントを見てください。中身についてのご質問はご遠慮願います。
<ファイルの指定>
起動すると次のような画面になります。「WAVファイルを開く」を押してファイルを指定すると、そのヘッダ情報が表示されます。下は先に8kHzに変換したファイルを開いたところで、サンプリングレートを見ると8000になっているのがわかります。
<COMポートの指定>
「WAVファイルを開く」の隣のコンボボックスはCOMポートを指定します。起動時にどのCOMポートが使えるか検出して、使えるものだけを表示します(COM10までしか判定していません。)。下の例ではA33FのUSBシリアルドライバをインストールしたときに確認した番号(COM8)を指定しています。A33FとつながっていないCOMポートを指定しないように注意して下さい。
<音声データの転送>
A33FのSDカードが512バイト単位での読み書きなので、アドレスも512バイト単位の指定になります。開いたファイルの音声部分を転送するには「転送」ボタンを押します。この時、アドレスに入れたアドレスがSDカードに書き込まれる際のアドレスになります。A33F側の受信ソフトウェアは次の節で説明します。この操作により、
1)シンクロバイト
2)命令番号
3)命令数
4)データのバイト数
5)アドレス
6)音声データ
の順に送信されます。
<音声データの再生>
念のため、送信したデータを再生するコマンドも用意しました。アドレスと長さをセットして「再生」を押すと再生します。上記の画面で長さが20になっているのは、元の音声データが10072バイトなので、512で割ると約19.67、つまりSDカードで20ブロック分になるので20にしています。SDカード側は、512に満たない端数のデータ数の場合は最後に0を入れてあります。0を連続で再生=無音です。
ということで、アドレスや長さは512バイト単位に計算して値をセットする必要があるので少々面倒ですが、とりあえず簡易版ということで。Windowsアプリに興味のある方はこの機会に少し勉強してみてください。
A33F側のソフトウェア
今回は前回のSDカードへの録音プログラムに追加する形でプログラムを作りました。プログラムは2つに分割しています。プロジェクト全体を圧縮しています。(右クリックで対象を保存)
WavPlay.lzh
いままでのような詳細は割愛しますのでコメントを見てください。
プログラムが長いので読むのが大変ですが、基本的には前回までのものに、UART1による通信を追加しています。WavPlay_2.cの最後の方の4つの関数が追加部分です。
コマンド部分はUART1割り込みで1文字づつ受信して、コマンドが全部そろったらフラグが立つ(U1RXstatが4になったら受信終了)ようになっています。
実際のデータ受信や、再生はmainループの中でコマンドの種類を判定して実行しています。
wavデータの受信は storeWavData( ) 関数で行います(WavPlay_2.cの下の方)。512バイト受信ごとに255の数値を返して書き込みタイミングを調整しています。SDカードの書き込みが全体の処理の中では一番遅いのでこのようなハンドリングが必要です。PC側では512バイト送信ごとに255が帰ってくるかを見て、255がきてから次の512バイトを送信しています。
wavデータの再生は前回行った再生とほぼ同じ内容です。バッファを2つ持ち、再生中に次の512バイトをセットして2つのバッファを交互にセットしています。
結果
結果は、8kHzにレートを落としたことで音質は下がりましたが、無事再生することができました。
今回ぐらいになってくると、どんどんプログラムが複雑になり、PCとの連携も出てきます。リニアPCMは単純に音の増減データだけなので、それをきちんとセットできれば音を再生することができるということだけ理解してください。このページを参考程度に、はじめから自分で作った方が速いかもしれません。
2007年12月27日
|