12半音階によるトーン生成
Révision | 05c64c80a10b324b375562a6070f403efa4d0028 |
---|---|
Taille | 3,567 octets |
l'heure | 2013-06-03 23:41:51 |
Auteur | suikan |
Message de Log | 最初のコミット |
/**
* @file uzume_callback.c
* @brief オーディオ信号処理を行うユーザー・コールバック
*/
#include "t_services.h"
#include "s_services.h"
#include "kernel_id.h"
#include "uzume.h"
#include "i2s_subsystem.h"
#include <fx32_nco.h>
#include <fract.h>
#include <limits.h>
#include <cdefBF592-A.h>
/**
* @brief 信号処理初期化関数
* @details
* この関数はUZUMEプラットフォームの初期化を行う。
* フィルタの構築や変数の初期化などを実行すると良い。
*
* @ingroup AUDIO
*/
/* Constant to create Hz on 48kHz sample*/
#define Hz (LONG_MAX/24000)
fract32 temperament[12] = {
523.25*Hz,
554.36*Hz,
587.33*Hz,
622.25*Hz,
659.25*Hz,
698.45*Hz,
739.99*Hz,
783.99*Hz,
830.61*Hz,
880.00*Hz,
932.33*Hz,
987.76*Hz
};
TNCO osc[12];
void init_audio(void)
{
/* ブロックサイズは UZUME_BLOCKSIZE マクロを使用すればわかる */
int i;
for ( i= 0; i<12; i++)
fract32_nco_init( &osc[i], temperament[i]);
// PF0-7はSW1-8に対応しており、入力として使う。
*pPORTFIO_DIR &= 0xFF00;
*pPORTFIO_INEN |= 0x00FF;
// PG8-11はSW9-12に対応しており、入力として使う。
*pPORTGIO_DIR &= 0xF0FF;
*pPORTGIO_INEN |= 0x0F00;
}
/* sw : 0-11 represents the sw1-12 */
int check_switch(int sw)
{
if ( sw < 8 )
{
return ( ! ( *pPORTFIO & (1<<sw) ) );
}
else
{
return ( ! ( * pPORTGIO & ( 1<< sw)));
}
}
/**
* @brief 信号処理関数
* @param input_left 左チャンネル0入力配列
* @param input_right 右チャンネル0入力配列
* @param output_left 左チャンネル0出力配列
* @param output_right 右チャンネル0出力配列
* @ingroup AUDIO
*
* ユーザーが信号処理を行う関数。オーディオ信号に同期して呼び出される。
* それぞれの引数は引数countがあらわす個数だけデータを持っている。
* データは24bit符号付整数。32bit変数に左詰で渡される。
*
* この関数はステレオ信号を2系統あつかえる。すなわち、系統0と系統1がそれぞれ左右チャンネルを持つ。
* この関数が使う資源で、あらかじめ初期化が必要なものは、@ref init_audio()の中で初期化しておく。
*/
void process_audio(
AUDIOSAMPLE input_left[],
AUDIOSAMPLE input_right[],
AUDIOSAMPLE output_left[],
AUDIOSAMPLE output_right[]
)
{
// ループ変数
int i;
fract32 sample;
fract32 volume;
fract32 cosout[UZUME_BLOCKSIZE], sinout[UZUME_BLOCKSIZE];
for (sample = 0; sample < UZUME_BLOCKSIZE; sample++) {
output_left[sample] = output_right[sample] = 0;
}
for (i = 0; i < 12; i++) {
// ch 3 のボリューム値(32bit)
volume = get_volume(3);
// i番目の音を生成
fract32_nco(&osc[i], cosout, sinout, UZUME_BLOCKSIZE);
// i番目のスイッチの音をチェック
if ( check_switch(i) )
volume = mult_fr1x32x32( LONG_MAX / 12 ,volume );
else
volume = 0;
// count個のサンプルすべてを処理する
for (sample = 0; sample < UZUME_BLOCKSIZE; sample++) {
output_left[sample] += mult_fr1x32x32( cosout[sample],volume );
output_right[sample] += mult_fr1x32x32( sinout[sample],volume );
}
}
}