USBオーディオ出力を試す
by K.I
2016/12/20〜
Index
- デジタルフィルタを、実際に作ってみたいと思ったんだけど、
- データをどうやって用意するかということで、ちょっと困った。
- 複雑な波形を生成するも、サンプリングするのも、やっぱり面倒なので、
- 普通のUSBシリアル送信で、高速に大量のデータを送るのは、自分には難しい。
- とりあえずUSB Audio出力で、どんなデータが出力されるのか調べてみた。
- これは、USB接続で、I2S出力やSPDIF出力が出来る
- I2Sって、I2Cみたいなものかな〜と思っていたんだけど、調べてみると単なるシリアル出力みたい
- これって、なかなか都合が良いんじゃないかな。
No. | Name | Description |
1 | DOUT | データ出力・16bit I2Sformat |
2 | LRCLKO | Left/Rightクロック出力 (サンプリングクロック) |
3 | BCKO | ビットクロック出力 |
4 | SCKO | システムクロック(256fs) |
5 | GND | グラウンド |
- ついでに、I2S入力のアンプとかないかな〜と探してみると、こんなのがあった。
No. | Name | Description |
1 | Vin | 2.5〜5.5Vだが、通常は+5Vとする |
2 | GND | グラウンド |
3 | SD_MODE | 0.16V以下:Shutdown、0.16〜0.77V:Left+Right、0.77〜1.4V:Right、1.4V以上:Left |
4 | GAIN | 15dB:100kΩPullDown、12dB:GND、9dB:default、6dB:Vin、3dB:100kΩPullUp |
5 | DIN | Data Input |
6 | BCLK | Bit Clock |
7 | LRCLK | Left/Right Clock |
- SD_MODE端子は、内部100kΩでPullDown、外部で1MΩPullUpされているので、約0.45V(L+R)、
- さらに例えば680kΩPullUpで約0.99V(R)、180kΩ以下でPullUpすれば約1.98V以上になる(L)
- モノラルアンプなので、ステレオにするためには、2個必要になる。
- USB Audio I/Fと、D級アンプ2個を、LRCLK,BCLK,DATAの3本で配線1して、スピーカーを鳴らせるようにした。
- それにしても、D級アンプは凄い。かなり大きな音量で鳴らしても、全然発熱しない。
- 周波数は、300〜350kHzぐらいで、Dutyも微妙に変化しているが、
- 音楽が鳴っていても、無音でも波形では区別が付かない。。
1GNDと+5V電源を入れると、5本になるけど。
[top]
- WindowsのUSBAudio出力が、どうなっているか調べてみる
- サンプリング周波数44.1kHz、16bitで正弦波を生成する(dds16.c)
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
//1秒分のデータを生成
#define FREQ (1000)
#define SAMPLE (44100) //サンプリング周波数
#define N (44100) //サンプル数
#define MAX 32767 //16bit
int sin_table[N/4+1];
void make_table(void)
{
int x;
for (x=0; x<=N/4 ;x++)
sin_table[x] = sin(2*M_PI/N*x)*MAX;
}
int sin_x(int x)
{
int xx;
xx = x%(N/4);
if (x < N/4*1) return sin_table[xx];
else if (x < N/4*2) return sin_table[N/4-xx];
else if (x < N/4*3) return -sin_table[xx];
else return -sin_table[N/4-xx];
}
main( int argc, char *argv[] )
{
int i, d, t=0;
double f, s;
f = FREQ;
s = SAMPLE;
make_table();
if (argc>1)
f = atof(argv[1]);
d = f*N/s;
for (i=0; i<s ;i++) {
printf("%d\n",sin_x(t));
t = (t+d)%N;
}
}
- 1kHzのWAVファイルを作成して、Windows Media Playerで出力してみる
- Saleaeのロジックアナライザのプロトコル解析機能2を使って、I2Sのデータを読んでみた。
- I2Sの設定がいまいち分かりづらかったけど、以下のように設定したら読めた
- Analyzer Settings (I2S/PCM)
- CLOCK: BCK
- FRAME: LRCLK
- DATA : DOUT
- DATA arrives MSB first
- DATA is valid (shuld be read) on the CLOCK rising edge
- 16 Bits/Word (Audio bit depth, bits/sample)
- FRAME signal transitions (changes state) twice each word.
- DATA bits are left-aligned with respect to FRAME edges
- Bits are right-shifted by one with respect to FRAME edges (I2S typical)
- Samples are signed (two's complement)
- Word select high is channel 2 (right) (I2S typical)
- Volumeを変えると、I2Sのデータ自体が小さくなる。
- 音を小さくすると、有効ビット数が減ってしまうことになるのか。。
- CSVファイルとして、Exportも出来るので、元のWAVファイルの計算値と比較してみた
- Volumeを100%で出力して、I2SのDout値と、元ファイルの値(計算値)を比較した
Dout | 計算値 | Dout/計算値 |
0 | 0 | - |
4582 | 4652 | 0.984952709 |
9072 | 9211 | 0.984909348 |
13378 | 13582 | 0.984980121 |
17412 | 17679 | 0.984897336 |
21092 | 21417 | 0.984825139 |
24344 | 24721 | 0.984749808 |
27104 | 27525 | 0.984704814 |
29312 | 29770 | 0.984615385 |
30928 | 31412 | 0.984591876 |
31916 | 32418 | 0.984514776 |
32260 | 32766 | 0.984557163 |
31952 | 32451 | 0.98462297 |
30994 | 31478 | 0.984624182 |
29407 | 29867 | 0.984598386 |
27225 | 27651 | 0.984593686 |
24491 | 24874 | 0.984602396 |
21261 | 21593 | 0.984624647 |
17600 | 17875 | 0.984615385 |
13583 | 13795 | 0.984632113 |
9288 | 9434 | 0.984524062 |
4808 | 4883 | 0.98464059 |
228 | 233 | 0.978540773 |
-4353 | -4421 | 0.984618865 |
-8847 | -8986 | 0.984531493 |
-13164 | -13370 | 0.984592371 |
-17212 | -17482 | 0.984555543 |
-20913 | -21240 | 0.98460452 |
-24192 | -24568 | 0.984695539 |
-26978 | -27397 | 0.984706355 |
-29220 | -29672 | 0.984766783 |
-30869 | -31345 | 0.984814165 |
-31892 | -32383 | 0.984837723 |
-32270 | -32765 | 0.984892416 |
-31993 | -32482 | 0.984945508 |
-31067 | -31542 | 0.984940714 |
-29511 | -29962 | 0.9849476 |
-27357 | -27775 | 0.984950495 |
-24648 | -25025 | 0.984935065 |
-21441 | -21768 | 0.984977949 |
-17798 | -18070 | 0.984947427 |
-13795 | -14006 | 0.984935028 |
-9513 | -9658 | 0.98498654 |
-5036 | -5114 | 0.984747751 |
-459 | -466 | 0.984978541 |
何故か、僅かに計算値よりDoutが小さい。
どうやら、0.985倍になっているようだ
- 100%で出力しているはずなのに、何故0.985倍になってしまうんだろう?
Dout | 計算値 | Dout-計算値 |
0 | 0 | 0 |
4652 | 4652 | 0 |
9211 | 9211 | 0 |
13582 | 13582 | 0 |
17679 | 17679 | 0 |
21417 | 21417 | 0 |
24720 | 24721 | -1 |
27525 | 27525 | 0 |
29770 | 29770 | 0 |
31411 | 31412 | -1 |
32418 | 32418 | 0 |
32766 | 32766 | 0 |
32451 | 32451 | 0 |
31478 | 31478 | 0 |
29868 | 29867 | 1 |
27651 | 27651 | 0 |
24875 | 24874 | 1 |
21593 | 21593 | 0 |
17874 | 17875 | -1 |
13795 | 13795 | 0 |
9434 | 9434 | 0 |
4883 | 4883 | 0 |
233 | 233 | 0 |
-4421 | -4421 | 0 |
-8986 | -8986 | 0 |
-13371 | -13370 | -1 |
-17482 | -17482 | 0 |
-21241 | -21240 | -1 |
-24568 | -24568 | 0 |
-27398 | -27397 | -1 |
-29671 | -29672 | 1 |
-31346 | -31345 | -1 |
-32383 | -32383 | 0 |
-32766 | -32765 | -1 |
-32482 | -32482 | 0 |
-31542 | -31542 | 0 |
-29963 | -29962 | -1 |
-27775 | -27775 | 0 |
-25025 | -25025 | 0 |
-21768 | -21768 | 0 |
-18070 | -18070 | 0 |
-14006 | -14006 | 0 |
-9658 | -9658 | 0 |
-5114 | -5114 | 0 |
-466 | -466 | 0 |
- 今度は、100%の値が出力されるようになった!
- でも、±1の雑音が乗っている。まぁこれは音のある部分だけではない。
- I2Sの出力を見ると、LRCLKとBCLKは常に出力されているが、BOUTは音が鳴っている時だけ出力される。
- ロジックアナライザで、BOUTの立ち上がりでトリガを掛けてデータを取っている
- LRCLKはサンプリング周波数で44.08kHz4、BCLKは2.667MHzだった
- だが1秒の音なのに、約1040msの長さがある
- 音が開始する約12ms前から、雑音が入り始める。
- 雑音は図の0〜12msの区間、実際の音データ出力は12msから始まる
- 音が終了してから、約28msの間は雑音が入っている。
- 図の 12ms(1012ms)までが実際の音データの出力、それ以降 40ms(1040ms)まで雑音
- 雑音は±1だけしか入っていないので、Windowsによって人為的に入っているっぽい
- これは、例えばI2S入力のアンプが、サスペンド状態になっていた場合に、
- 音が鳴るより12ms前から信号が入ることで、回路を起動させるためにあるのかもしれない5
- まぁ実際±1の雑音とか0.985倍の処理とかは、音で聞く分には全く問題にならないレベルの話しだけど、
- 自分がやろうとしているいろいろな実験的には、データ確認がいちいち面倒6になってしまうなぁ。
- それから、リミッタを無効にすると、ちょっとWindowsが不安定になるようなので、注意。
2I2Sの解析機能があって良かった。これがなかったら、かなり大変だったと思う。
3まさか、0.985というキーワードで見つかるとは思わなかったんだけど。。
4サンプリング周波数は44.1kHzのはずなので、これは測定誤差なのかな?
5まぁ好意的に見ればだけど。なにか理由があるとは思うんだけど、やっぱり邪魔だなぁ。。
6実際、0.985倍になっている理由が分かるのに随分と時間を食ってしまった。
[top]
- Mac Miniがあるので、そちらでもUSB Audio出力を試してみる
- Macから出力して、I2S信号を確認したら、ちょっと不可解なデータだった。
- 最初の立ち上がりが少し遅い。フィルタが掛かっているようにみえる
Dout | 計算値 |
0 | 0 |
118 | 4652 |
4092 | 9211 |
8649 | 13582 |
12412 | 17679 |
16460 | 21417 |
19918 | 24721 |
23159 | 27525 |
26029 | 29770 |
28335 | 31412 |
30309 | 32418 |
31626 | 32766 |
32494 | 32451 |
32767 | 31478 |
32471 | 29867 |
31668 | 27651 |
30257 | 24874 |
28386 | 21593 |
25994 | 17875 |
23165 | 13795 |
19954 | 9434 |
16376 | 4883 |
12545 | 233 |
8477 | -4421 |
4276 | -8986 |
2 | -13370 |
-4280 | -17482 |
-8477 | -21240 |
-12541 | -24568 |
-16382 | -27397 |
-19946 | -29672 |
-23171 | -31345 |
-25994 | -32383 |
-28377 | -32765 |
-30272 | -32482 |
-31650 | -31542 |
-32486 | -29962 |
-32767 | -27775 |
-32486 | -25025 |
-31650 | -21768 |
-30272 | -18070 |
-28376 | -14006 |
-25995 | -9658 |
-23169 | -5114 |
-19946 | -466 |
-16383 | 4190 |
-12539 | 8762 |
-8481 | 13156 |
-4276 | 17284 |
1 | 21062 |
4277 | 24413 |
8480 | 27269 |
12539 | 29572 |
16383 | 31276 |
19947 | 32346 |
23170 | 32761 |
25996 | 32512 |
28377 | 31604 |
30272 | 30056 |
31650 | 27898 |
32486 | 25175 |
32766 | 21942 |
32486 | 18264 |
31650 | 14217 |
30272 | 9881 |
28376 | 5344 |
25995 | 700 |
23169 | -3958 |
19946 | -8537 |
16383 | -12942 |
12540 | -17085 |
8480 | -20882 |
4276 | -24256 |
0 | -27138 |
あぁ、グラフを描いてみるとよく分かるが、周期が全然違っている
どうやら、48ks/sのようだ
- MacOSXでは、デフォルトで48ks/sで出力されるらしい
- 波形の立ち上がりが遅いのは、サンプルレート変換されている所為か。。
- アプリケーション/ユーティリティ/Audio MIDI設定.appを起動して、USB AUDIO DACを見ると、
- 2ch 16ビット整数48.0kHz になっているので、
- 2ch 16ビット整数44.1kHz に変更する
Dout | 計算値 |
0 | 0 |
4652 | 4652 |
9211 | 9211 |
13582 | 13582 |
17679 | 17679 |
21417 | 21417 |
24721 | 24721 |
27525 | 27525 |
29770 | 29770 |
31412 | 31412 |
32418 | 32418 |
32766 | 32766 |
32451 | 32451 |
31478 | 31478 |
29867 | 29867 |
27651 | 27651 |
24874 | 24874 |
21593 | 21593 |
17875 | 17875 |
13795 | 13795 |
9434 | 9434 |
4883 | 4883 |
233 | 233 |
-4421 | -4421 |
-8986 | -8986 |
-13370 | -13370 |
-17482 | -17482 |
-21240 | -21240 |
-24568 | -24568 |
-27397 | -27397 |
-29672 | -29672 |
-31345 | -31345 |
-32383 | -32383 |
-32765 | -32765 |
-32482 | -32482 |
-31542 | -31542 |
-29962 | -29962 |
-27775 | -27775 |
-25025 | -25025 |
-21768 | -21768 |
-18070 | -18070 |
-14006 | -14006 |
-9658 | -9658 |
-5114 | -5114 |
-466 | -466 |
4190 | 4190 |
- 今度は、完全に一致した
- Windwosと違って、ピークリミッタも、変なノイズも無く、そのまま出力されている。
[top]
- ではUnixから出力してみたい。でもレンタルサーバなので、現状、自宅にあるUnixマシンは、、
- ということで raspberryPi から出力してみる
- こちらの記事を参考に、というかそのままですが
$ cat /proc/asound/cards
0 [ALSA ]: bcm2835 - bcm2835 ALSA
bcm2835 ALSA
- USBに挿してみると、USB Audioとして、ちゃんと認識された
$ cat /proc/asound/cards
0 [ALSA ]: bcm2835 - bcm2835 ALSA
bcm2835 ALSA
1 [DAC ]: USB-Audio - USB AUDIO DAC
BurrBrown from Texas Instruments USB AUDIO DAC at usb-3f980000.usb-1.5, full
$ uname -a
Linux raspberrypi 4.4.34-v7+ #930 SMP Wed Nov 23 15:20:41 GMT 2016 armv7l GNU/Linux
- /usr/share/alsa/alsa.conf を変更して、rebootする
#
# ALSA library configuration file
#
# pre-load the configuration files
@hooks [
{
func load
files [
{
@func concat
strings [
{ @func datadir }
"/alsa.conf.d/"
]
}
"/etc/asound.conf"
# "~/.asoundrc" # コメントアウトする
]
errors false
}
]
:
:
#
defaults.ctl.card 1 # 0→1に変更
defaults.pcm.card 1 # 同上
defaults.pcm.device 0
defaults.pcm.subdevice -1
:
:
$ aplay sin1000.wav
再生中 WAVE 'sin1000.wav' : Signed 16 bit Little Endian, レート 44100 Hz, モノラル
- USBで出力された結果を見ると、48ks/sだった。。どうやらリサンプリングされているらしい。
- aplayの、rオプションで44100を指定してみたが、変わらず。
- /usr/share/alsa/alsa.confで、48000の記述を探して、44100に書き換えてみた
defaults.pcm.dmix.rate 44100
- rebootしてから、aplayで出力すると、今度はそのままのデータが出力された!
- まぁ、はじめから48ks/sのデータを出力すれば、デフォルトの設定でOKのはず
[top]
- デジタルフィルタの実験のために、生成したデータをそのまま出力したい。
- USB Audioで、44.1ks/sのデータをそのまま出力することが出来るか、確かめてみたわけだけど、
- Windowsの場合、ピークリミッタが掛かってしまって、そのままの出力にはならない。
- ピークリミッタを無効にしても、何故か±1の雑音が載ってしまう
- 但し、自分の環境はWindows7なので、最新のWindows10だと状況は違う可能性もある
- MacOSXや、RaspberryPi(Unix)の場合、デフォルトでは、48ks/s出力になっているようだ。
- リサンプリングされるので、元のデータそのままとはいかない。
- でも、出力を44.1ks/sに設定すれば、そのままのデータが出力できるようだ。
- 元々が48ks/sのデータを出力すれば、デフォルト設定でもそのまま出力されるはず
- ということで何とか使えそうなことが分かったんだけど、いろいろ調べてみると、
- でも、USB Audioは、いろんな環境でUSBケーブル1本で使えるのが便利だ。
- それなりの速度で、ほぼ途切れなく出力が出来る方法として使えると思う
- 長くなったので、これはこれで一旦、纏めておこうと思う。
- こういう USBスピーカーを分解して、そこからI2S信号取れないものだろうか。。
- でも単にUSB電源のスピーカーというのもあるので、間違いないように!
[top]
[プログラムの部屋に戻る]