ZOOM U-22 分解・特性測定

14_252_1u22p.jpg
ZOOM U-22というオーディオインターフェイスを購入しました。分解・特性測定を行っておきます。



【分解】

▽中身画像 ZOOM U-22 Handy Audio Interface Gut Shots
14_252_2u22pi.jpg14_252_3u22pm.jpg
以下のICが確認できました。8ピンのオペアンプっぽいICの型番は読み取れませんでした。
・マイコン LPC1820FBD144
・クロックジェネレータ AK8142
・オーディオコーデック TLV320AIC3101
・電源 RT9971

絶縁型DC-DCコンバータを使った電源ではなさそうですがローノイズです。アナログGNDとデジタルGND(と思われる部分)がところどころコンデンサで繋いであるのは、ノイズ対策なのかもしれません。

OUTPUTノブは0.5dB単位で動いているようなのでおそらくデジタル制御です。GAINノブは連続的な動きなのでアナログ回路だと思われます。
※LINE IN使用時GAINノブは無効



【特性測定】

PHONES出力からLINE IN入力へステレオケーブルを接続した状態で特性を測定しました。OUTPUTノブは10です。

Windowsの場合、コントロールパネルのZOOM U-22 Control Panel(またはC:\Program Files\ZOOM\U-22 Driver\zmu22audiocp.exe)から Sampling Rate を 96000 Hz に設定しておきます。

<PHONE出力>
最大無歪出力: 約 0.7 Vrms (OUTPUTノブ 10、WaveGene振幅 -5.5dB)
出力インピーダンス: 10 Ω (マニュアルより)

<LINE IN入力>
最大無歪入力: 約 0.75 Vrms (CLIP SIGランプが赤に点灯)
入力インピーダンス: 22 kΩ (マニュアルより)

<WaveGene設定>
サンプリング周波数: 96000 ビット長: 24 チャンネル数: Stereo
・歪率測定 サイン波 100Hz 1kHz 10kHz FFT用に最適化(FFTサンプル数16384) -6dB
・周波数特性測定 ユーザー波形 FLATSWEEP_016384.WAV -6dB

WaveGeneサイトにあるサンプリングレート48kHzのユーザー波形サンプルを使っています。本来は96kHz用の波形を用意すべきですが、20kHz以上の周波数も問題ないようなのでそのまま利用しています。

<WaveSpectra設定>
Avg: 300
[FFT] サンプルデータ数: 16384 窓関数: なし(矩形)
[再生/録音] フォーマット: 96000 s/s 24 bit Stereo

※DELL製PCでドライバをMMEにした場合、周波数特性が乱れました(別の東芝製PCでは問題なし)。PCやドライバとの相性があるのかもしれません。

▽ノイズレベル(POWER SOURCE: USB)
14_252_4u22n.png
入力なしの時でも高域にいくつかピークが見えますが、特に問題ないでしょう。電池駆動でもほぼ同じ結果でした。

▽歪率・周波数特性
14_252_5u22f.png
マニュアルの周波数特性には±2 dB(20 Hz - 40 kHz)と記載がありますが、それよりも良いのではないかと思います。

タグ : 周波数特性 歪率 

2020年

あけましておめでとうございます。今年もよろしくお願いいたします。
デジタルエフェクターの知識がそれなりに身に付いてきたように思うので、ブログ更新を進めていきたいです。

STM32 内蔵フラッシュメモリへのデータ保存

HALライブラリを利用し、STM32の内蔵フラッシュメモリへデータを保存します。これにより電源を切ってもデータを残したままにすることができます。下記参考ページにも詳細な内容がありますので、併せてご参照ください。
STM32 + HAL Flashの書き込み・読み込み



フラッシュメモリへのデータ保存時には、単純に書き込み関数を呼び出せばよいわけではなく、あらかじめ書き込む場所を消去しておく必要があります。さらに、消去等の操作前にはロックを解除しなければいけません。つまり下記の流れとなります。
・ロック解除→消去→書き込み→再度ロック

フラッシュメモリはセクタという単位に分割されており、消去操作時にはセクタごとに消去します。STM32F401REのセクタ7の場合、フラッシュメモリの終わり側128kB分が全て消えることになります。

<STM32F4、F7での書き込みサンプルコード>
テストとして配列を書き込みます。NUCLEO-F401REで動作確認しました。セクタの開始アドレスはそれぞれのICのリファレンスマニュアルをご確認ください。
const uint32_t flash_addr = 0x08060000; // データ保存先(セクタ7)開始アドレス
uint16_t testData[8] = {1, 3, 5, 7, 2, 4, 6, 8}; // 書き込むデータ

void saveData()
{
/* フラッシュ ロック解除 */
HAL_FLASH_Unlock();

/* フラッシュ 消去 */
FLASH_EraseInitTypeDef erase; // 消去に関する構造体を定義
uint32_t error = 0; // エラーコードを格納する変数
erase.TypeErase = FLASH_TYPEERASE_SECTORS; // 消去方法: セクタ消去
erase.Sector = FLASH_SECTOR_7; // 消去するセクタ: セクタ7
erase.NbSectors = 1; // 消去するセクタの数: 1
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; // 電圧設定
HAL_FLASHEx_Erase(&erase, &error); // 消去

/* フラッシュ 書き込み */
uint32_t addr = flash_addr; // 書き込み先アドレスを代入
for (int i = 0; i < 8; i++)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr, testData[i]); // 書き込み
addr += 2; // 2バイト(16ビット)分アドレスを進める
}

/* フラッシュ ロック */
HAL_FLASH_Lock();
}
今回は16ビットのデータを書き込んでいますが、8ビットであれば「FLASH_TYPEPROGRAM_BYTE」を使い、アドレスは1バイトずつ進めます(32ビットであれば「FLASH_TYPEPROGRAM_WORD」を使い、アドレスは4バイトずつ進めます)。

<データ読み出し>
保存したデータを読み出す場合は特別な操作は必要なく、下記のように記載します。
uint32_t addr = flash_addr;
testData[0] = *((uint16_t*)addr);
「(uint16_t*)」で書き込み先アドレスをポインタ型へキャストし、そのポインタ(アドレス)にあるデータを「*」で読み出しています。何も書き込まれていない場合は、ビットが全て1のデータ(uint16_tなら65535)が読み出されます。



<STM32H7での書き込みサンプルコード>
セクタの他にバンク1と2があるため、バンク指定が追加になっています。また、書き込みはFLASHWORD(256ビット)単位限定で、256ビットのデータを準備しなければいけないようです。データ読み出しについては上記と同じです。NUCLEO-H743ZI2で動作確認しました。
const uint32_t flash_addr = 0x081E0000; // データ保存先(バンク2 セクタ7)開始アドレス
uint16_t testData[16] = {1, 3, 5, 7, 2, 4, 6, 8, 9, 7, 5, 3, 0, 8, 6, 4}; // 書き込むデータ

void saveData()
{
/* フラッシュ ロック解除 */
HAL_FLASH_Unlock();

/* フラッシュ 消去 */
FLASH_EraseInitTypeDef erase; // 消去に関する構造体を定義
uint32_t error = 0; // エラーコードを格納する変数
erase.TypeErase = FLASH_TYPEERASE_SECTORS; // 消去方法: セクタ消去
erase.Banks = FLASH_BANK_2; // 消去するバンク: バンク2
erase.Sector = FLASH_SECTOR_7; // 消去するセクタ: セクタ7
erase.NbSectors = 1; // 消去するセクタの数: 1
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; // 電圧設定
HAL_FLASHEx_Erase(&erase, &error); // 消去

/* フラッシュ 書き込み */
uint32_t addr = flash_addr; // 書き込み先アドレスを代入
HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, (uint32_t)testData); // 書き込み
addr += 32; // 続けて他のデータを書き込む場合は32バイト(256ビット)分アドレスを進める

/* フラッシュ ロック */
HAL_FLASH_Lock();
}



<リンカスクリプトについて>
内蔵フラッシュメモリにはプログラムが書き込まれています。万が一大きなプログラムとなった場合には、データ保存したいフラッシュ領域と重なってしまうおそれがあります。そこで、プログラムの領域とデータ保存の領域を分けておきます。

STM32CubeIDEのプロジェクトフォルダ内に、リンカスクリプトと呼ばれるSTM32○○○○_FLASH.ldというファイルがあります。このファイル内のMEMORYの記述を変更すればOKです。例えばSTM32F401REのセクタ7(開始アドレス0x08060000)をデータ保存領域(DATA)とする場合は下記の記述とします。
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K
DATA (rx) : ORIGIN = 0x08060000, LENGTH = 128K
}

タグ : マイコン 

YAMAHA SBV風ベース(ボディ自作)

16_155_1sbv.jpg
ヤマハSBVは生産終了品で、中古でもなかなか出回っていないようです。独特のナスのよう形状が気に入り、ボディを自作しました。

今回使用したピックアップはジャズベース用のものなので、多分スタンダードな音です。軽いペグにしたにも関わらず、少しヘッド落ち気味となりました。ATLANSIAのネックはフレットすり合わせとフレットのエッジ処理が必要なのですが、太めで丈夫だと思います。

塗装がやはり難しかったです。下塗りの塗料が湿気のせいかザラザラになってしまいました。色合いは想定通りでした(血の色のような感じ)。塗装3ヶ月後、塗料は乾いているかと思いきや、1日放置するとギタースタンドに敷いていた綿100%タオルがくっついてきました。かなり長い期間吊るして保管した方がよさそうです。

以下、使用したパーツをメモしておきます。



【ネック】 ATLANSIA PS-020(ジャズベースタイプネック スケール34インチ)

ペグ:Hipshot HB6Y 1/2" Ultralite
テンションバー:SCUD SR-GB475C
ナット:牛骨



【ボディ】 アイチ木材加工 アルダーボディ材ベース用Aグレード

ネックジョイントプレートなし、M4ローゼットワッシャー使用
ネックジョイントビス:ステンレス 皿木ねじ 4.1mm×45mm
ピックガード:ALLPARTS JAPAN Pickguard Board ホワイト 3プライ
ポット:東京コスモス RV24 500kΩ Aカーブ
ジャック:Switchcraft #112BX ステレオジャック(補強のためアルミプレートをピックガードに貼付)
ピックアップ:DiMarzio Ultra Jazz(DP149)→プレベピックアップカバーへ取付
ブリッジ:GOTOH J510SJ
ストラップピン:JIM DUNLOP ロックピン



【塗料】
アサヒペン 木部用プライマー
和信ペイント ラッカーサンディングシーラー
アサヒペン アスペンラッカースプレー 白(下塗り)
アサヒペン クリエイティブカラースプレー 61ディープレッド・58マットクリヤ
ギターワークス 水性 導電塗料

タグ : エレキベース 

デシベル計算の高速化

前回記事でべき乗(pow)や対数(log)の演算は遅いということが分かりました。デジタルエフェクターではデシベル計算をよく使うため、これらの演算を高速化することを考えます。(以下、C言語を前提とした記述となっています。)



< dB x → 電圧比(倍率) y >

通常の計算は y = powf( 10.0f, x / 20.0f ) ですが、500サイクル程度かかります。そこでテーブル引きという方法を使います。あらかじめ表(ルックアップテーブル)を用意しておき、そこから値を取り出して計算する方法です。

今回テーブルは-128dB~+128dBの範囲で1dBステップとしました。小数点以下の部分については線形補間(2点間を一次関数に当てはめる)で近似します。コードは下記の通りです。dbtovolTable.hファイルはGitHubに置いています。

#include "dbtovolTable.h"

float dbtovol(float x)
{
x += 128.0f;
uint8_t xi = (uint8_t) x;
return dbtormsTable[xi] + (dbtormsTable[xi+1] - dbtormsTable[xi]) * (x - xi);
}

xiにはuint8_tの0~255が入るので、テーブル配列のサイズは257にすればよいです。もちろん入力値が範囲外の場合は正しい値が出力されません。誤差は最大0.015dBで、実用には充分だと思います。サイクル数は約30となり大幅に高速化できました。



< 電圧比(倍率) x → dB y >

通常の計算は y = 20.0f * log10f( x ) ですが、230サイクル程度かかります。こちらもテーブル引きを利用したいところですが、等比級数的なテーブルを準備する方法がわかりませんでした。膨大な量の配列を準備している例もありますが、メモリが少ない場合には無理があります。

今回はsqrtf演算(=1/2乗)が高速なことを利用することにしました。以下のように式を変形します。
log x
= log ( x1/2 )2
= 2 log x1/2
・・・
= 32 log x1/32
あとは x1/32 とdBの関係を三次関数で近似します。コードは以下の通りです。

#include <math.h>

float voltodb(float x)
{
x = sqrtf(sqrtf(sqrtf(sqrtf(sqrtf(x)))));
return - 559.57399f + 995.83468f * x
- 591.85129f * x * x + 155.60596f * x * x * x;
}

使用範囲は0.00001(-100dB)~1(0dB) 推奨、最大誤差0.016dBです。電圧比というより音量変換を見据えた範囲としています。範囲を超えると誤差が増えますが、極端に外れた値にはなりません。サイクル数は約90で、効果はそれなりでした。

他にもいろいろな方法を試したのですが、条件分岐を入れると意外とサイクル数が増えてしまう等、なかなかこれといった方法が見つかりませんでした。場合によっては通常のlog10fを使うことになりそうです。

管理人

管理人

自己紹介のページ
記事一覧
Twitter
GitHub

ブログ内検索
カテゴリー
タグ

自作エフェクター   レイアウト   回路図   歪み   周波数特性   マイコン   PureData   波形・倍音   RaspberryPi   エレキギター   アンプ   歪率   エフェクター自作方法   エレキベース   真空管   コーラス   ピックアップ   静音ギター   ヘッドフォンアンプ   擬似ギター出力   市販エフェクター   アコースティックギター   ブースター   コンデンサ   ソロギター   ポールピース   イコライザー   コンプレッサー   ビブラート   フェイザー   トレモロ   TAB譜   ディレイ   DIY_Layout_Creator   ワウ   オートワウ   バッファー   

最近の記事
最新コメント
Twitter
RSS
メールフォーム
当ブログに関するお問い合わせはこちらからお願いします。 ※FAQ(よくある質問)もお読みください。

お名前
メールアドレス
件名
本文

アクセスカウンター