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]
[プログラムの部屋に戻る]
⇒ Disqusの広告がうるさすぎるので基本は非表示にしました