Sound Generator Library

Fork of Sound_Generator by GR-PEACH_producer_meeting

Information

Japanese version is available in lower part of this page.
このページの後半に日本語版が用意されています.

Sound Generator

What is this?

Driver library for Sound Generator that is function of RZ/A1H.

API

Driver Wrapper API

You can use music playback function to call following APIs.

void piano4int_start( const int8_t *scores[SDG_CH_TOTAL], PIANO4INT_CB callback )

descriptionstarts music playback
argumentsscores : music data of each chanel. The number of channels is specified by SDG_CH_TOTAL.
callback : call back function by playing synchonized marker
return value-
explanationStarts music playback.
For channels not to play, set NULL to the corresponding element of scores[].
Playback is controlled by interrupt handler.
So, this function returns after initialization.
"Callback" function will be called from interrupt handler when synchronized marker is played.

void piano4int_stop( bool force )

descriptionstops music playback
argumentsforce : When this value is 1, force stop will be executed (not implemented).
return value-
explanationStop misic playback.
This function returns after finishing music playback of all channels.
This function stops interrupts, but does not release objects.

bool piano4int_status( void )

descriptionGets the plaback status
arguments-
return valueThe plaback status
explanationGets the plaback status.
If any of the channel plays music, this function returns true.

typedef void (*PIANO4INT_CB)( uint32_t channel, uint32_t value )

descriptioncall back function by playing synchonized marker
argumentschannel : Channel number
value : Synchronized marker ID
return value-
explanationThis is a user function call back by playing synchronized marker..
The argument "value" is set to the number that is described after synchronized marker.
This function is called in interrupt hander, so please shorten the processing of this function.


Driver API

int32_t R_SDG_Open( uint32_t channel, R_SDG_CLOCK clock )

descriptionopens driver
argumentschannel : Channel number (0~3)
clock : clock
return valuesuccess : DEVDRV_SUCCESS
error : DEVDRV_ERROR, etc.
explanationThis function initializes sound generator specified by argument "channel".
"clock" to set the clock to be used in the internal sound generator from either from P0φ/2 to P0φ/16.
Sample code accepts channel 1 and channel 3 only. If channel 0 or 2 is specified, this function returns an error.

int32_t R_SDG_Close( uint32_t channel )

descriptionCloses driver
argumentschannel : Channel number (0~3)
return valuesuccess : DEVDRV_SUCCESS
error : DEVDRV_ERROR,etc.
explanationThis function terminates sound generator specified by argument "channel".
In Sample code, once this function is called, clock supply is stopped, this driver will not work until calling R_SDG_Open().
If target channel has not initialized by R_SDG_Open(), this function returns error code.

int32_t R_SDG_Tone( uint32_t channel, NOTE *note )

descriptionGenerates single tone.
argumentschannel : Channel number (0~3)
note : Tone parameters
return valuesuccess : DEVDRV_SUCCESS
error : DEVDRV_ERROR,etc.
explanationThis function generates single tone. Tone is specified by argument "note".
Pitch is determined by the following equation.

Reference frequency = "clock" / [note->sfs]
Pitch = [Reference frequency] / ( 2 × [note->tone] )

Loudness is determined by note->loud. note->loud specifies the duty of the square wave to be syncthesized sound to be output.
Period square wave is high will be calculated in [note->loud / 256].
Attenuation rate is specified by note->attenuation. Attenuation is achieved by make the note->loud to 31/32 with the given period by note->attenuation.
If target channel has not initialized by R_SDG_Open(), this function returns error code.

User Definition Functions

int32_t Userdef_SDG0_Open( void )

int32_t Userdef_SDG1_Open( void )

int32_t Userdef_SDG2_Open( void )

int32_t Userdef_SDG3_Open( void )

descriptionOpen driver
argument-
return valuesuccess : DEVDRV_SUCCESS
error : the other
explanationUser of this driver must create this function.
This function is called from R_SDG_Open(), so user must create this function for each 4 channels.
In this function, user must operate following operation.
・Supplies clock to the sound generator.
・Sets pin-mux for the sound generator.
In the case this function is succeed, please set the return value of this function to DEVDRV_SUCCESS. The other value indicate an error and copy to the return value of R_SDG_Open() function.
In the sample code, initializing routine is described for channel 1 and 3, and an error routine is described for channel 0 and 2.

int32_t Userdef_SDG0_Close( void )

int32_t Userdef_SDG1_Close( void )

int32_t Userdef_SDG2_Close( void )

int32_t Userdef_SDG3_Close( void )

descriptionClose driver
argument-
return valuesuccess : DEVDRV_SUCCESS
error : the other
explanationUser of this driver must create this function.
This function is called from R_SDG_Close(), so user must create this function for each 4 channels.
In this function, user must operate following operation.
・Sets pin-mux for GPIO.
・Stops the clock supply to the sound generator
In the case this function is succeed, please set the return value of this function to DEVDRV_SUCCESS. The other value indicate an error and copy to the return value of R_SDG_Close() function.
In the sample code, uninitializing routine is described for channel 1 and 3, and an error routine is described for channel 0 and 2.

structures

typedef struct {
    UINT8_T TONE;		/* TONE VALUE ( 0 < TONE <= 127 )	*/
    UINT8_T SFS;		/* SFS VALUE ( 0 < SFS <= 255 )		*/
    UINT8_T LOUD;		/* LD VALUE ( 0 <= LD <= 255 )		*/
    UINT8_T ATTENUATION;	/* ATTENUATION VALUE			*/
} NOTE;

This structure specifies single tone.This structure is used in argument of R_SDG_Tone().

membermeaninghardware register
tonespecifies single toneTONE[6:0]
sfsreferrence frequencySFS[7:0]
loudstores the duty data for pulse output.LD[7:0]
attenuationTurns the attenuator function on and off, and select the attenuation cycleDPF[2:0]

enumerate

typedef enum {
    R_SDG_CLOCK_2  = 0,
    R_SDG_CLOCK_4  = 1,
    R_SDG_CLOCK_8  = 2,
    R_SDG_CLOCK_16 = 3,
} R_SDG_CLOCK;

Selects the operating clock.

enumereatemeaning
R_SDG_CLOCK_2P0φ/2
R_SDG_CLOCK_4P0φ/4
R_SDG_CLOCK_8P0φ/8
R_SDG_CLOCK_16P0φ/16


typedef enum {
    R_SDG_ATT_OFF = 0,
    R_SDG_ATT_1	  = 1,
    R_SDG_ATT_2	  = 2,
    R_SDG_ATT_4	  = 3,
    R_SDG_ATT_8	  = 4,
    R_SDG_ATT_16  = 5,
    R_SDG_ATT_32  = 6,
} R_SDG_ATTENUATION;

Turns the attenuator function on and off, and select the attenuation cycle.

enumeratemeaning
R_SDG_ATT_OFFAttenuator function is off.
R_SDG_ATT_1Attenuates at the TONE frequency
R_SDG_ATT_2Attenuates at the TONE frequency/2
R_SDG_ATT_4Attenuates at the TONE frequency/4
R_SDG_ATT_8Attenuates at the TONE frequency/8
R_SDG_ATT_16Attenuates at the TONE frequency/16
R_SDG_ATT_32Attenuates at the TONE frequency/32




サウンドジェネレータ

概要

RZ/A1Hに搭載されているサウンドジェネレータを使用するためのライブラリです。

API

Driver Wrapper API

下記に示すAPIはDriver APIをコールすることで楽曲再生機能を実現します。

void piano4int_start( const int8_t *scores[SDG_CH_TOTAL], PIANO4INT_CB callback )

概要楽曲再生開始関数
引数scores : SDG_CH_TOTALで指定されるチャネル数分の楽譜
callback : 同期指示関数
戻り値なし
解説楽曲の再生を開始します。
再生しないチャネルは、scores[ ]の該当する要素にNULLを設定します。
再生は、内部でもっているTickerオブジェクトに従って、すべて割り込みで行われます。
従って、この関数は初期化を終えると戻ってきます。
同期指示関数callbackは、楽曲データに埋め込まれた同期マーカを再生したとき、割り込みから呼び出されます。

void piano4int_stop( bool force )

概要楽曲再生停止関数
引数force : 強制停止フラグ(未実装)
戻り値なし
解説楽曲の再生を停止します。
この関数を呼び出すと、すべての楽曲を再生し終えた後、戻ってきます。
割り込みは使用しなくなりますが、オブジェクトの解放はしません。

bool piano4int_status( void )

概要楽曲再生状態取得関数
引数なし
戻り値再生状態
解説現在の再生の状況を取得します。
与えられた楽曲の一つでも再生中ならば、trueを返します。

typedef void (*PIANO4INT_CB)( uint32_t channel, uint32_t value )

概要同期提示関数
引数channel : チャネル番号
value : 同期マーカID
戻り値なし
解説楽曲データに組み込んだ同期マーカ付音符を再生するときに呼び出されるユーザ関数です。
valueは、同期マーカの次に書かれている1~2桁の数字を整数型にしたものです。
割り込みの中から呼ばれますので、処理は軽めにしてください。あまり長いと音がずれます。


Driver API

int32_t R_SDG_Open( uint32_t channel, R_SDG_CLOCK clock )

概要サウンドジェネレータ初期化関数
引数channel : チャネル番号 (0~3)
clock : 動作クロック
戻り値正常終了 : DEVDRV_SUCCESS
エラー終了 : DEVDRV_ERRORなど
解説チャネル番号で指定したサウンドジェネレータを初期化します。
動作クロックは、P0φ/2~P0φ/16から、今後使用するTONEやLOUDNESSに合わせて選択します。
サンプルコードでは、チャネル1及びチャネル3だけが使用できます。チャネル0及びチャネル2を指定した場合はエラー終了します。

int32_t R_SDG_Close( uint32_t channel )

概要サウンドジェネレータ終了関数
引数channel : チャネル番号 (0~3)
戻り値正常終了 : DEVDRV_SUCCESS
エラー終了 : DEVDRV_ERRORなど
解説指定したチャネルのサウンドジェネレータの使用を終了します。サンプルコードでは、クロックの供給も停止しますので、
再びR_SDG_Open( )で初期化するまで使用できなくなります。
R_SDG_Open( )を呼び出していないチャネルを指定した場合はエラー終了します。

int32_t R_SDG_Tone( uint32_t channel, NOTE *note )

概要単音作成関数
引数channel : チャネル番号 (0~3)
note : トーン設定パラメータ
戻り値正常終了 : DEVDRV_SUCCESS
エラー終了 : DEVDRV_ERRORなど
解説単音を出力します。音はnoteで指定します。
note->tone、note->sfs、R_SDG_Open( )で指定した動作クロックから、次の式で音の高さを決めます。

基準周波数 = 動作クロック/sfs
TONE周波数 = 基準周波数/( 2 × tone )

note->loudで音の大きさを指定します。loudは出力する音に合成する方形波のデューティ比で、
loud /256が方形波のHighの区間になります。
note->attenuationで減衰率を指定します。指定した周期ごとに、loudを31/32にすることで減衰します。
R_SDG_Open( )を呼び出していないチャネルを指定した場合はエラー終了します。

ユーザ定義関数

int32_t Userdef_SDG0_Open( void )

int32_t Userdef_SDG1_Open( void )

int32_t Userdef_SDG2_Open( void )

int32_t Userdef_SDG3_Open( void )

概要サウンドジェネレータ初期化ユーザ定義関数
引数なし
戻り値正常終了 : DEVDRV_SUCCESS
エラー終了 : その他
解説このドライバの利用者が作成する関数です。
R_SDG_Open( )から呼び出される関数で、4チャネル分の関数が必要です。
使用するサウンドジェネレータのサウンドジェネレータ初期化ユーザ定義関数では、
最低限、次のことを実施してください。

・サウンドジェネレータにクロックを供給します。
・サウンドジェネレータが使う出力ピンの設定をします。

また、正常に終了したとき、DEVDRV_SUCCESSを返してください。この値以外はエラーとみなし、
R_SDG_Open( )の戻り値になります。
サンプルコードでは、チャネル1及びチャネル3は初期化処理を行い、チャネル0及びチャネル2はエラーになります。

int32_t Userdef_SDG0_Close( void )

int32_t Userdef_SDG1_Close( void )

int32_t Userdef_SDG2_Close( void )

int32_t Userdef_SDG3_Close( void )

概要サウンドジェネレータ終了ユーザ定義関数
引数なし
戻り値正常終了 : DEVDRV_SUCCESS
エラー終了 : その他
解説このドライバの利用者が作成する関数です。
R_SDG_Close( )から呼び出される関数で、4チャネル分の関数が必要です。
これらの関数では、次のことを実施してください。

・サウンドジェネレータが使う出力ピンをGPIOに変更します。
・サウンドジェネレータへのクロックの供給を停止します。

また、正常に終了したとき、DEVDRV_SUCCESSを返してください。
この値以外はエラーとみなし、R_SDG_Close( )の戻り値になります。
サンプルコードでは、チャネル1及びチャネル3は終了処理を行い、チャネル0及びチャネル2はエラーになります。

構造体

typedef struct {
    UINT8_T TONE;		/* TONE VALUE ( 0 < TONE <= 127 )	*/
    UINT8_T SFS;		/* SFS VALUE ( 0 < SFS <= 255 )		*/
    UINT8_T LOUD;		/* LD VALUE ( 0 <= LD <= 255 )		*/
    UINT8_T ATTENUATION;	/* ATTENUATION VALUE			*/
} NOTE;

単音を表す構造体です。R_SDG_Tone( )の引数で使用します。意味と設定するビットを次に示します。

要素意味ビット名
tone音色を決める値ですTONE[6:0]
sfs基準周波数を決める値ですSFS[7:0]
loud出力パルスのデューティ比を決める値ですLD[7:0]
attenuation出力の減衰率を決める値ですDPF[2:0]

列挙型

typedef enum {
    R_SDG_CLOCK_2  = 0,
    R_SDG_CLOCK_4  = 1,
    R_SDG_CLOCK_8  = 2,
    R_SDG_CLOCK_16 = 3,
} R_SDG_CLOCK;

動作クロックを表す列挙型です。それぞれ、次の意味をもちます。

要素意味
R_SDG_CLOCK_2P0φ/2
R_SDG_CLOCK_4P0φ/4
R_SDG_CLOCK_8P0φ/8
R_SDG_CLOCK_16P0φ/16


typedef enum {
    R_SDG_ATT_OFF = 0,
    R_SDG_ATT_1	  = 1,
    R_SDG_ATT_2	  = 2,
    R_SDG_ATT_4	  = 3,
    R_SDG_ATT_8	  = 4,
    R_SDG_ATT_16  = 5,
    R_SDG_ATT_32  = 6,
} R_SDG_ATTENUATION;

減衰率を表す列挙型です。それぞれ、次の意味をもちます。

要素意味
R_SDG_ATT_OFF減衰しません
R_SDG_ATT_1TONE周波数で減衰します
R_SDG_ATT_2TONE周波数の1/2で減衰します
R_SDG_ATT_4TONE周波数の1/4で減衰します
R_SDG_ATT_8TONE周波数の1/8で減衰します
R_SDG_ATT_16TONE周波数の1/16で減衰します
R_SDG_ATT_32TONE周波数の1/32で減衰します
Committer:
Osamu Nakamura
Date:
Mon Apr 24 18:32:45 2017 +0900
Revision:
1:cd3d332d4499
Parent:
0:a3a1d4768307
Revised piano4int.cpp so that it can be compiled with GCC ARM Embedded

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MasaoHamanaka 0:a3a1d4768307 1 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 2 * DISCLAIMER
MasaoHamanaka 0:a3a1d4768307 3 * This software is supplied by Renesas Electronics Corporation and is only
MasaoHamanaka 0:a3a1d4768307 4 * intended for use with Renesas products. No other uses are authorized. This
MasaoHamanaka 0:a3a1d4768307 5 * software is owned by Renesas Electronics Corporation and is protected under
MasaoHamanaka 0:a3a1d4768307 6 * all applicable laws, including copyright laws.
MasaoHamanaka 0:a3a1d4768307 7 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
MasaoHamanaka 0:a3a1d4768307 8 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
MasaoHamanaka 0:a3a1d4768307 9 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
MasaoHamanaka 0:a3a1d4768307 10 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
MasaoHamanaka 0:a3a1d4768307 11 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
MasaoHamanaka 0:a3a1d4768307 12 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
MasaoHamanaka 0:a3a1d4768307 13 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
MasaoHamanaka 0:a3a1d4768307 14 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
MasaoHamanaka 0:a3a1d4768307 15 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
MasaoHamanaka 0:a3a1d4768307 16 * Renesas reserves the right, without notice, to make changes to this software
MasaoHamanaka 0:a3a1d4768307 17 * and to discontinue the availability of this software. By using this software,
MasaoHamanaka 0:a3a1d4768307 18 * you agree to the additional terms and conditions found by accessing the
MasaoHamanaka 0:a3a1d4768307 19 * following link:
MasaoHamanaka 0:a3a1d4768307 20 * http://www.renesas.com/disclaimer
MasaoHamanaka 0:a3a1d4768307 21 * Copyright (C) 2012 - 2015 Renesas Electronics Corporation. All
MasaoHamanaka 0:a3a1d4768307 22 * rights reserved.
MasaoHamanaka 0:a3a1d4768307 23 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 24
MasaoHamanaka 0:a3a1d4768307 25 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 26 Includes <System Includes> , "Project Includes"
MasaoHamanaka 0:a3a1d4768307 27 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 28 #include <stdio.h>
MasaoHamanaka 0:a3a1d4768307 29 #include <ctype.h>
MasaoHamanaka 0:a3a1d4768307 30 #include <stdint.h>
MasaoHamanaka 0:a3a1d4768307 31 extern "C" {
MasaoHamanaka 0:a3a1d4768307 32 #include "iodefine.h"
MasaoHamanaka 0:a3a1d4768307 33 #include "dev_drv.h"
MasaoHamanaka 0:a3a1d4768307 34 #include "devdrv_sdg.h"
MasaoHamanaka 0:a3a1d4768307 35 }
MasaoHamanaka 0:a3a1d4768307 36 #include "mbed.h"
MasaoHamanaka 0:a3a1d4768307 37 #include "PinNames.h"
MasaoHamanaka 0:a3a1d4768307 38
MasaoHamanaka 0:a3a1d4768307 39 #include "piano4int.h"
MasaoHamanaka 0:a3a1d4768307 40
MasaoHamanaka 0:a3a1d4768307 41 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 42 Macro definitions
MasaoHamanaka 0:a3a1d4768307 43 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 44 #define ASSERT( eval ) \
MasaoHamanaka 0:a3a1d4768307 45 if (!(eval)) { \
MasaoHamanaka 0:a3a1d4768307 46 printf( \
MasaoHamanaka 0:a3a1d4768307 47 "%s: failed! at %d in %s\n", \
MasaoHamanaka 0:a3a1d4768307 48 #eval, \
MasaoHamanaka 0:a3a1d4768307 49 __LINE__, \
MasaoHamanaka 0:a3a1d4768307 50 __FILE__); \
MasaoHamanaka 0:a3a1d4768307 51 }
MasaoHamanaka 0:a3a1d4768307 52
MasaoHamanaka 0:a3a1d4768307 53 /* message to caller */
MasaoHamanaka 0:a3a1d4768307 54 #define UNIT_MSG (32)
MasaoHamanaka 0:a3a1d4768307 55
MasaoHamanaka 0:a3a1d4768307 56
MasaoHamanaka 0:a3a1d4768307 57 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 58 Typedef definitions
MasaoHamanaka 0:a3a1d4768307 59 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 60 /* a sound generator unit */
MasaoHamanaka 0:a3a1d4768307 61 typedef struct {
MasaoHamanaka 0:a3a1d4768307 62 uint16_t speed; /* count of a tempo */
MasaoHamanaka 0:a3a1d4768307 63 uint8_t loudness; /* current loudness */
MasaoHamanaka 0:a3a1d4768307 64 uint16_t count; /* remain of time */
MasaoHamanaka 0:a3a1d4768307 65 NOTE note; /* a next note */
MasaoHamanaka 0:a3a1d4768307 66 const int8_t *score; /* a next score */
MasaoHamanaka 0:a3a1d4768307 67 const int8_t *top; /* top of a score */
MasaoHamanaka 0:a3a1d4768307 68 uint8_t channel; /* channel number */
MasaoHamanaka 0:a3a1d4768307 69 #ifdef UNIT_MSG
MasaoHamanaka 0:a3a1d4768307 70 char msg[UNIT_MSG]; /* message */
MasaoHamanaka 0:a3a1d4768307 71 #endif
MasaoHamanaka 0:a3a1d4768307 72 } UNIT;
MasaoHamanaka 0:a3a1d4768307 73
MasaoHamanaka 0:a3a1d4768307 74
MasaoHamanaka 0:a3a1d4768307 75 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 76 Imported global variables and functions (from other files)
MasaoHamanaka 0:a3a1d4768307 77 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 78
MasaoHamanaka 0:a3a1d4768307 79
MasaoHamanaka 0:a3a1d4768307 80 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 81 Exported global variables and functions (to be accessed by other files)
MasaoHamanaka 0:a3a1d4768307 82 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 83
MasaoHamanaka 0:a3a1d4768307 84
MasaoHamanaka 0:a3a1d4768307 85 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 86 Private global variables and functions
MasaoHamanaka 0:a3a1d4768307 87 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 88 /* interrupt routine */
MasaoHamanaka 0:a3a1d4768307 89 static void play_score(void);
MasaoHamanaka 0:a3a1d4768307 90
MasaoHamanaka 0:a3a1d4768307 91
MasaoHamanaka 0:a3a1d4768307 92 /* all work area for piano */
MasaoHamanaka 0:a3a1d4768307 93 struct {
MasaoHamanaka 0:a3a1d4768307 94 UNIT unit[SDG_CH_TOTAL];
MasaoHamanaka 0:a3a1d4768307 95 uint16_t fin;
MasaoHamanaka 0:a3a1d4768307 96 Ticker metronome; /* base tempo */
MasaoHamanaka 0:a3a1d4768307 97 PIANO4INT_CB callback;
MasaoHamanaka 0:a3a1d4768307 98 } pianoT;
MasaoHamanaka 0:a3a1d4768307 99
MasaoHamanaka 0:a3a1d4768307 100
MasaoHamanaka 0:a3a1d4768307 101 /* init params for sound generator */
MasaoHamanaka 0:a3a1d4768307 102 static const struct {
MasaoHamanaka 0:a3a1d4768307 103 uint16_t channel;
MasaoHamanaka 0:a3a1d4768307 104 R_SDG_CLOCK clock;
MasaoHamanaka 0:a3a1d4768307 105 } unitHW[SDG_CH_TOTAL] = {
MasaoHamanaka 0:a3a1d4768307 106 { DEVDRV_CH_0, R_SDG_CLOCK_4 },
MasaoHamanaka 0:a3a1d4768307 107 { DEVDRV_CH_1, R_SDG_CLOCK_4 },
MasaoHamanaka 0:a3a1d4768307 108 { DEVDRV_CH_2, R_SDG_CLOCK_4 },
MasaoHamanaka 0:a3a1d4768307 109 { DEVDRV_CH_3, R_SDG_CLOCK_4 },
MasaoHamanaka 0:a3a1d4768307 110 };
MasaoHamanaka 0:a3a1d4768307 111
MasaoHamanaka 0:a3a1d4768307 112
MasaoHamanaka 0:a3a1d4768307 113 /* dummy entry of score (no sounds)*/
MasaoHamanaka 0:a3a1d4768307 114 static const int8_t noscore[] = "";
MasaoHamanaka 0:a3a1d4768307 115
MasaoHamanaka 0:a3a1d4768307 116 /* parameters of a rest */
MasaoHamanaka 0:a3a1d4768307 117 static const NOTE rest4 = {
MasaoHamanaka 0:a3a1d4768307 118 0, /* tone */
MasaoHamanaka 0:a3a1d4768307 119 0, /* sfs */
MasaoHamanaka 0:a3a1d4768307 120 0, /* loud */
MasaoHamanaka 0:a3a1d4768307 121 0, /* attenuation */
MasaoHamanaka 0:a3a1d4768307 122 };
MasaoHamanaka 0:a3a1d4768307 123
MasaoHamanaka 0:a3a1d4768307 124
MasaoHamanaka 0:a3a1d4768307 125 /* table of notes */
MasaoHamanaka 0:a3a1d4768307 126 static const struct {
MasaoHamanaka 0:a3a1d4768307 127 uint8_t tone;
MasaoHamanaka 0:a3a1d4768307 128 uint8_t sfs;
MasaoHamanaka 0:a3a1d4768307 129 } note_timing[MAXOCTAVE][MAXNOTE] = {
MasaoHamanaka 0:a3a1d4768307 130 { /* octave 0 */
MasaoHamanaka 0:a3a1d4768307 131 { 0, 0 }, /* -A */
MasaoHamanaka 0:a3a1d4768307 132 { 0, 0 }, /* -A# */
MasaoHamanaka 0:a3a1d4768307 133 { 0, 0 }, /* -B */
MasaoHamanaka 0:a3a1d4768307 134 { 124, 255 }, /* -C */
MasaoHamanaka 0:a3a1d4768307 135 { 117, 255 }, /* -C# */
MasaoHamanaka 0:a3a1d4768307 136 { 111, 255 }, /* -D */
MasaoHamanaka 0:a3a1d4768307 137 { 105, 255 }, /* -D# */
MasaoHamanaka 0:a3a1d4768307 138 { 99, 255 }, /* -E */
MasaoHamanaka 0:a3a1d4768307 139 { 93, 255 }, /* -F */
MasaoHamanaka 0:a3a1d4768307 140 { 88, 255 }, /* -F# */
MasaoHamanaka 0:a3a1d4768307 141 { 83, 255 }, /* -G */
MasaoHamanaka 0:a3a1d4768307 142 { 78, 255 }, /* -G# */
MasaoHamanaka 0:a3a1d4768307 143 { 0, 0 }, /* -R */
MasaoHamanaka 0:a3a1d4768307 144 },
MasaoHamanaka 0:a3a1d4768307 145 { /* octave 1 */
MasaoHamanaka 0:a3a1d4768307 146 { 86, 220 }, /* A */
MasaoHamanaka 0:a3a1d4768307 147 { 81, 220 }, /* A# */
MasaoHamanaka 0:a3a1d4768307 148 { 76, 220 }, /* B */
MasaoHamanaka 0:a3a1d4768307 149 { 72, 220 }, /* C */
MasaoHamanaka 0:a3a1d4768307 150 { 68, 220 }, /* C# */
MasaoHamanaka 0:a3a1d4768307 151 { 64, 220 }, /* D */
MasaoHamanaka 0:a3a1d4768307 152 { 60, 220 }, /* D# */
MasaoHamanaka 0:a3a1d4768307 153 { 57, 220 }, /* E */
MasaoHamanaka 0:a3a1d4768307 154 { 54, 220 }, /* F */
MasaoHamanaka 0:a3a1d4768307 155 { 51, 220 }, /* F# */
MasaoHamanaka 0:a3a1d4768307 156 { 48, 220 }, /* G */
MasaoHamanaka 0:a3a1d4768307 157 { 45, 220 }, /* G# */
MasaoHamanaka 0:a3a1d4768307 158 { 0, 0 }, /* R */
MasaoHamanaka 0:a3a1d4768307 159 },
MasaoHamanaka 0:a3a1d4768307 160 { /* octave 2 */
MasaoHamanaka 0:a3a1d4768307 161 { 49, 190 }, /* +A */
MasaoHamanaka 0:a3a1d4768307 162 { 47, 190 }, /* +A# */
MasaoHamanaka 0:a3a1d4768307 163 { 44, 190 }, /* +B */
MasaoHamanaka 0:a3a1d4768307 164 { 41, 190 }, /* +C */
MasaoHamanaka 0:a3a1d4768307 165 { 39, 190 }, /* +C# */
MasaoHamanaka 0:a3a1d4768307 166 { 37, 190 }, /* +D */
MasaoHamanaka 0:a3a1d4768307 167 { 35, 190 }, /* +D# */
MasaoHamanaka 0:a3a1d4768307 168 { 33, 190 }, /* +E */
MasaoHamanaka 0:a3a1d4768307 169 { 31, 190 }, /* +F */
MasaoHamanaka 0:a3a1d4768307 170 { 29, 190 }, /* +F# */
MasaoHamanaka 0:a3a1d4768307 171 { 27, 190 }, /* +G */
MasaoHamanaka 0:a3a1d4768307 172 { 26, 190 }, /* +G# */
MasaoHamanaka 0:a3a1d4768307 173 { 0, 0 }, /* +R */
MasaoHamanaka 0:a3a1d4768307 174 },
MasaoHamanaka 0:a3a1d4768307 175 { /* octave 3 */
MasaoHamanaka 0:a3a1d4768307 176 { 31, 150 }, /* *A */
MasaoHamanaka 0:a3a1d4768307 177 { 29, 150 }, /* *A# */
MasaoHamanaka 0:a3a1d4768307 178 { 28, 150 }, /* *B */
MasaoHamanaka 0:a3a1d4768307 179 { 26, 150 }, /* *C */
MasaoHamanaka 0:a3a1d4768307 180 { 25, 150 }, /* *C# */
MasaoHamanaka 0:a3a1d4768307 181 { 23, 150 }, /* *D */
MasaoHamanaka 0:a3a1d4768307 182 { 22, 150 }, /* *D# */
MasaoHamanaka 0:a3a1d4768307 183 { 21, 150 }, /* *E */
MasaoHamanaka 0:a3a1d4768307 184 { 19, 150 }, /* *F */
MasaoHamanaka 0:a3a1d4768307 185 { 18, 150 }, /* *F# */
MasaoHamanaka 0:a3a1d4768307 186 { 17, 150 }, /* *G */
MasaoHamanaka 0:a3a1d4768307 187 { 16, 150 }, /* *G# */
MasaoHamanaka 0:a3a1d4768307 188 { 0, 0 }, /* *R */
MasaoHamanaka 0:a3a1d4768307 189 },
MasaoHamanaka 0:a3a1d4768307 190 };
MasaoHamanaka 0:a3a1d4768307 191
MasaoHamanaka 0:a3a1d4768307 192
MasaoHamanaka 0:a3a1d4768307 193 /* name table of notes */
MasaoHamanaka 0:a3a1d4768307 194 #ifdef UNIT_MSG
Osamu Nakamura 1:cd3d332d4499 195 static const char *note_name[MAXNOTE] = {
MasaoHamanaka 0:a3a1d4768307 196 "A",
MasaoHamanaka 0:a3a1d4768307 197 "A#",
MasaoHamanaka 0:a3a1d4768307 198 "B",
MasaoHamanaka 0:a3a1d4768307 199 "C",
MasaoHamanaka 0:a3a1d4768307 200 "C#",
MasaoHamanaka 0:a3a1d4768307 201 "D",
MasaoHamanaka 0:a3a1d4768307 202 "D#",
MasaoHamanaka 0:a3a1d4768307 203 "E",
MasaoHamanaka 0:a3a1d4768307 204 "F",
MasaoHamanaka 0:a3a1d4768307 205 "F#",
MasaoHamanaka 0:a3a1d4768307 206 "G",
MasaoHamanaka 0:a3a1d4768307 207 "G#",
MasaoHamanaka 0:a3a1d4768307 208 "R",
MasaoHamanaka 0:a3a1d4768307 209 };
MasaoHamanaka 0:a3a1d4768307 210 #endif /*UNIT_MSG*/
MasaoHamanaka 0:a3a1d4768307 211
MasaoHamanaka 0:a3a1d4768307 212
MasaoHamanaka 0:a3a1d4768307 213 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 214 * Function Name: piano4int_start
MasaoHamanaka 0:a3a1d4768307 215 * Description : Play the score thru sound generator.
MasaoHamanaka 0:a3a1d4768307 216 * : This function receives the sound language,
MasaoHamanaka 0:a3a1d4768307 217 * : and plays specified sound language.
MasaoHamanaka 0:a3a1d4768307 218 * Arguments : const int8_t *scores : score
MasaoHamanaka 0:a3a1d4768307 219 * : PIANO4INT_CB callback : callback function
MasaoHamanaka 0:a3a1d4768307 220 * Return Value : none
MasaoHamanaka 0:a3a1d4768307 221 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 222 void piano4int_start(const int8_t *scores[SDG_CH_TOTAL], PIANO4INT_CB callback)
MasaoHamanaka 0:a3a1d4768307 223 {
MasaoHamanaka 0:a3a1d4768307 224 const int8_t *score; /* pointer to score */
MasaoHamanaka 0:a3a1d4768307 225 uint16_t speed; /* sound speed */
MasaoHamanaka 0:a3a1d4768307 226 int32_t ch; /* channel no */
MasaoHamanaka 0:a3a1d4768307 227 int32_t ret; /* function result */
MasaoHamanaka 0:a3a1d4768307 228
MasaoHamanaka 0:a3a1d4768307 229 /* prepare for playing the score */
MasaoHamanaka 0:a3a1d4768307 230 for (ch = 0; ch < SDG_CH_TOTAL; ch++) {
MasaoHamanaka 0:a3a1d4768307 231 if (scores[ch] == NULL) {
MasaoHamanaka 0:a3a1d4768307 232 /* score is not specified */
MasaoHamanaka 0:a3a1d4768307 233 pianoT.unit[ch].score = noscore;
MasaoHamanaka 0:a3a1d4768307 234 pianoT.unit[ch].top = noscore;
MasaoHamanaka 0:a3a1d4768307 235 } else {
MasaoHamanaka 0:a3a1d4768307 236 /* prepare for playing a score */
MasaoHamanaka 0:a3a1d4768307 237 score = scores[ch];
MasaoHamanaka 0:a3a1d4768307 238
MasaoHamanaka 0:a3a1d4768307 239 /* get the speed */
MasaoHamanaka 0:a3a1d4768307 240 speed = 0;
MasaoHamanaka 0:a3a1d4768307 241 while (isdigit(*score)) {
MasaoHamanaka 0:a3a1d4768307 242 speed = (speed * 10) + ((*score++) - '0');
MasaoHamanaka 0:a3a1d4768307 243 }
MasaoHamanaka 0:a3a1d4768307 244 if (0 == speed) {
MasaoHamanaka 0:a3a1d4768307 245 /* can not play the score */
Osamu Nakamura 1:cd3d332d4499 246 printf("speed[%d]:%d, can not play, there is no speed information.\n", (int)ch, speed);
MasaoHamanaka 0:a3a1d4768307 247 return;
MasaoHamanaka 0:a3a1d4768307 248 } else {
Osamu Nakamura 1:cd3d332d4499 249 printf("speed[%d]:%d\n", (int)ch, speed);
MasaoHamanaka 0:a3a1d4768307 250 /* calculate a base speed for ticker */
MasaoHamanaka 0:a3a1d4768307 251 pianoT.unit[ch].speed = BASESPEED / speed;
MasaoHamanaka 0:a3a1d4768307 252
MasaoHamanaka 0:a3a1d4768307 253 /* default loudness (unsupported to change) */
MasaoHamanaka 0:a3a1d4768307 254 pianoT.unit[ch].loudness = DEFLOUDNESS;
MasaoHamanaka 0:a3a1d4768307 255
MasaoHamanaka 0:a3a1d4768307 256 /* set top of a score */
MasaoHamanaka 0:a3a1d4768307 257 pianoT.unit[ch].top = score;
MasaoHamanaka 0:a3a1d4768307 258 pianoT.unit[ch].score = score;
MasaoHamanaka 0:a3a1d4768307 259
MasaoHamanaka 0:a3a1d4768307 260 /* play no sounds */
MasaoHamanaka 0:a3a1d4768307 261 pianoT.unit[ch].count = 0;
MasaoHamanaka 0:a3a1d4768307 262
MasaoHamanaka 0:a3a1d4768307 263 /* rest4 */
MasaoHamanaka 0:a3a1d4768307 264 pianoT.unit[ch].note = rest4;
MasaoHamanaka 0:a3a1d4768307 265
MasaoHamanaka 0:a3a1d4768307 266 /* channel number */
MasaoHamanaka 0:a3a1d4768307 267 pianoT.unit[ch].channel = unitHW[ch].channel;
MasaoHamanaka 0:a3a1d4768307 268
MasaoHamanaka 0:a3a1d4768307 269 #ifdef UNIT_MSG
MasaoHamanaka 0:a3a1d4768307 270 /* message */
MasaoHamanaka 0:a3a1d4768307 271 pianoT.unit[ch].msg[0] = '\0';
MasaoHamanaka 0:a3a1d4768307 272 #endif
MasaoHamanaka 0:a3a1d4768307 273
MasaoHamanaka 0:a3a1d4768307 274 /* Initialize Sound Generator */
MasaoHamanaka 0:a3a1d4768307 275 ret = R_SDG_Open(unitHW[ch].channel, unitHW[ch].clock);
MasaoHamanaka 0:a3a1d4768307 276 ASSERT(0 == ret);
MasaoHamanaka 0:a3a1d4768307 277 }
MasaoHamanaka 0:a3a1d4768307 278 }
MasaoHamanaka 0:a3a1d4768307 279 }
MasaoHamanaka 0:a3a1d4768307 280
MasaoHamanaka 0:a3a1d4768307 281 /* set callback function */
MasaoHamanaka 0:a3a1d4768307 282 pianoT.callback = callback;
MasaoHamanaka 0:a3a1d4768307 283
MasaoHamanaka 0:a3a1d4768307 284 /* clear flags to finish playing */
MasaoHamanaka 0:a3a1d4768307 285 pianoT.fin = 0;
MasaoHamanaka 0:a3a1d4768307 286
MasaoHamanaka 0:a3a1d4768307 287 /* start the metronome (unit: 1ms) */
MasaoHamanaka 0:a3a1d4768307 288 pianoT.metronome.attach_us(&play_score, 1000.0);
MasaoHamanaka 0:a3a1d4768307 289 }
MasaoHamanaka 0:a3a1d4768307 290
MasaoHamanaka 0:a3a1d4768307 291 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 292 * Function Name: piano4int_stop
MasaoHamanaka 0:a3a1d4768307 293 * Description : Stop the sounds through sound generator.
MasaoHamanaka 0:a3a1d4768307 294 * Arguments : bool force : flag to stop forcedly (now, ignored)
MasaoHamanaka 0:a3a1d4768307 295 * Return Value : none
MasaoHamanaka 0:a3a1d4768307 296 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 297 void piano4int_stop(bool force)
MasaoHamanaka 0:a3a1d4768307 298 {
MasaoHamanaka 0:a3a1d4768307 299 int32_t ch;
MasaoHamanaka 0:a3a1d4768307 300 int32_t ret;
MasaoHamanaka 0:a3a1d4768307 301
MasaoHamanaka 0:a3a1d4768307 302 /* wait until sounds stop */
MasaoHamanaka 0:a3a1d4768307 303 do {
MasaoHamanaka 0:a3a1d4768307 304 /* wait 10.0 sec */
MasaoHamanaka 0:a3a1d4768307 305 wait_us(10.0 * 1000.0);
MasaoHamanaka 0:a3a1d4768307 306 #ifdef UNIT_MSG
MasaoHamanaka 0:a3a1d4768307 307 for (ch = 0; ch < SDG_CH_TOTAL; ch++) {
MasaoHamanaka 0:a3a1d4768307 308 if ('\0' != pianoT.unit[ch].msg[0]) {
MasaoHamanaka 0:a3a1d4768307 309 printf(&pianoT.unit[ch].msg[0]);
MasaoHamanaka 0:a3a1d4768307 310 pianoT.unit[ch].msg[0] = '\0';
MasaoHamanaka 0:a3a1d4768307 311 }
MasaoHamanaka 0:a3a1d4768307 312 }
MasaoHamanaka 0:a3a1d4768307 313 #endif /*UNIT_MSG*/
MasaoHamanaka 0:a3a1d4768307 314 } while (pianoT.fin != ((1 << SDG_CH_TOTAL) - 1));
MasaoHamanaka 0:a3a1d4768307 315 /* all scores finished */
MasaoHamanaka 0:a3a1d4768307 316
MasaoHamanaka 0:a3a1d4768307 317 /* stops the metronome */
MasaoHamanaka 0:a3a1d4768307 318 pianoT.metronome.detach();
MasaoHamanaka 0:a3a1d4768307 319
MasaoHamanaka 0:a3a1d4768307 320 /* stop all sound generators */
MasaoHamanaka 0:a3a1d4768307 321 for (ch = 0; ch < SDG_CH_TOTAL; ch++) {
MasaoHamanaka 0:a3a1d4768307 322 if (pianoT.unit[ch].top != noscore) {
MasaoHamanaka 0:a3a1d4768307 323 /* stop sound generator */
MasaoHamanaka 0:a3a1d4768307 324 ret = R_SDG_Close(unitHW[ch].channel);
MasaoHamanaka 0:a3a1d4768307 325 ASSERT(0 == ret);
MasaoHamanaka 0:a3a1d4768307 326 }
MasaoHamanaka 0:a3a1d4768307 327 }
MasaoHamanaka 0:a3a1d4768307 328 }
MasaoHamanaka 0:a3a1d4768307 329
MasaoHamanaka 0:a3a1d4768307 330 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 331 * Function Name: piano4int_status
MasaoHamanaka 0:a3a1d4768307 332 * Description : Get the flag to finish playing the score
MasaoHamanaka 0:a3a1d4768307 333 * Arguments : none
MasaoHamanaka 0:a3a1d4768307 334 * Return Value : The flag
MasaoHamanaka 0:a3a1d4768307 335 * Note : Output the comment if the macro "UNIT_MSG" is defined
MasaoHamanaka 0:a3a1d4768307 336 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 337 bool piano4int_status(void)
MasaoHamanaka 0:a3a1d4768307 338 {
MasaoHamanaka 0:a3a1d4768307 339 #ifdef UNIT_MSG
MasaoHamanaka 0:a3a1d4768307 340 int32_t ch;
MasaoHamanaka 0:a3a1d4768307 341
MasaoHamanaka 0:a3a1d4768307 342 /* output the comments from interrupts */
MasaoHamanaka 0:a3a1d4768307 343 for (ch = 0; ch < SDG_CH_TOTAL; ch++) {
MasaoHamanaka 0:a3a1d4768307 344 if ('\0' != pianoT.unit[ch].msg[0]) {
MasaoHamanaka 0:a3a1d4768307 345 printf(&pianoT.unit[ch].msg[0]);
MasaoHamanaka 0:a3a1d4768307 346 pianoT.unit[ch].msg[0] = '\0';
MasaoHamanaka 0:a3a1d4768307 347 }
MasaoHamanaka 0:a3a1d4768307 348 }
MasaoHamanaka 0:a3a1d4768307 349 #endif
MasaoHamanaka 0:a3a1d4768307 350
MasaoHamanaka 0:a3a1d4768307 351 return (pianoT.fin != ((1 << SDG_CH_TOTAL) - 1));
MasaoHamanaka 0:a3a1d4768307 352 }
MasaoHamanaka 0:a3a1d4768307 353
MasaoHamanaka 0:a3a1d4768307 354
MasaoHamanaka 0:a3a1d4768307 355 /******************************************************************************
MasaoHamanaka 0:a3a1d4768307 356 * Function Name: play_score
MasaoHamanaka 0:a3a1d4768307 357 * Description : Play the score on interrupt
MasaoHamanaka 0:a3a1d4768307 358 * Arguments : none
MasaoHamanaka 0:a3a1d4768307 359 * Return Value : none
MasaoHamanaka 0:a3a1d4768307 360 ******************************************************************************/
MasaoHamanaka 0:a3a1d4768307 361 void play_score(void)
MasaoHamanaka 0:a3a1d4768307 362 {
MasaoHamanaka 0:a3a1d4768307 363 UNIT *unit;
MasaoHamanaka 0:a3a1d4768307 364 const int8_t *score;
MasaoHamanaka 0:a3a1d4768307 365 uint16_t octave;
MasaoHamanaka 0:a3a1d4768307 366 uint16_t key;
MasaoHamanaka 0:a3a1d4768307 367 uint16_t pitch;
MasaoHamanaka 0:a3a1d4768307 368 uint16_t dot;
MasaoHamanaka 0:a3a1d4768307 369 uint16_t tie;
MasaoHamanaka 0:a3a1d4768307 370 uint8_t loud;
MasaoHamanaka 0:a3a1d4768307 371 uint16_t duration;
MasaoHamanaka 0:a3a1d4768307 372 uint16_t value;
MasaoHamanaka 0:a3a1d4768307 373 uint16_t ch;
MasaoHamanaka 0:a3a1d4768307 374 bool err;
MasaoHamanaka 0:a3a1d4768307 375
MasaoHamanaka 0:a3a1d4768307 376 for (ch = 0; ch < SDG_CH_TOTAL; ch++) {
MasaoHamanaka 0:a3a1d4768307 377 /* Check finish flag */
MasaoHamanaka 0:a3a1d4768307 378 if (0 != (pianoT.fin & (1 << ch))) {
MasaoHamanaka 0:a3a1d4768307 379 continue; /* finish */
MasaoHamanaka 0:a3a1d4768307 380 }
MasaoHamanaka 0:a3a1d4768307 381
MasaoHamanaka 0:a3a1d4768307 382 if (0 == pianoT.unit[ch].count) {
MasaoHamanaka 0:a3a1d4768307 383 unit = &pianoT.unit[ch];
MasaoHamanaka 0:a3a1d4768307 384 score = unit->score;
MasaoHamanaka 0:a3a1d4768307 385
MasaoHamanaka 0:a3a1d4768307 386 if ('\0' == *score) {
MasaoHamanaka 0:a3a1d4768307 387 /* set finish flag */
MasaoHamanaka 0:a3a1d4768307 388 pianoT.fin |= (1 << ch);
MasaoHamanaka 0:a3a1d4768307 389 continue;
MasaoHamanaka 0:a3a1d4768307 390 }
MasaoHamanaka 0:a3a1d4768307 391
MasaoHamanaka 0:a3a1d4768307 392 /* Initialize parameters */
MasaoHamanaka 0:a3a1d4768307 393 octave = 0;
MasaoHamanaka 0:a3a1d4768307 394 key = 0;
MasaoHamanaka 0:a3a1d4768307 395 pitch = 0;
MasaoHamanaka 0:a3a1d4768307 396 dot = 0;
MasaoHamanaka 0:a3a1d4768307 397 tie = 0;
MasaoHamanaka 0:a3a1d4768307 398 err = false;
MasaoHamanaka 0:a3a1d4768307 399
MasaoHamanaka 0:a3a1d4768307 400 /* skip some spaces */
MasaoHamanaka 0:a3a1d4768307 401 while (' ' == *score) {
MasaoHamanaka 0:a3a1d4768307 402 score++;
MasaoHamanaka 0:a3a1d4768307 403 }
MasaoHamanaka 0:a3a1d4768307 404
MasaoHamanaka 0:a3a1d4768307 405 /* octave */
MasaoHamanaka 0:a3a1d4768307 406 switch (*score) {
MasaoHamanaka 0:a3a1d4768307 407 case OCTAVE0_CHAR: { octave = OCTAVE_LEVEL_0; score++; break; }
MasaoHamanaka 0:a3a1d4768307 408 case OCTAVE1_CHAR: { octave = OCTAVE_LEVEL_1; score++; break; }
MasaoHamanaka 0:a3a1d4768307 409 case OCTAVE2_CHAR: { octave = OCTAVE_LEVEL_2; score++; break; }
MasaoHamanaka 0:a3a1d4768307 410 case OCTAVE3_CHAR: { octave = OCTAVE_LEVEL_3; score++; break; }
MasaoHamanaka 0:a3a1d4768307 411 default: { octave = OCTAVE_LEVEL_1; break; }
MasaoHamanaka 0:a3a1d4768307 412 }
MasaoHamanaka 0:a3a1d4768307 413
MasaoHamanaka 0:a3a1d4768307 414 /* key */
MasaoHamanaka 0:a3a1d4768307 415 switch (toupper(*score)) {
MasaoHamanaka 0:a3a1d4768307 416 case NOTE_DO_CHAR: { key = KEY_C; score++; break; }
MasaoHamanaka 0:a3a1d4768307 417 case NOTE_RE_CHAR: { key = KEY_D; score++; break; }
MasaoHamanaka 0:a3a1d4768307 418 case NOTE_MI_CHAR: { key = KEY_E; score++; break; }
MasaoHamanaka 0:a3a1d4768307 419 case NOTE_FA_CHAR: { key = KEY_F; score++; break; }
MasaoHamanaka 0:a3a1d4768307 420 case NOTE_SO_CHAR: { key = KEY_G; score++; break; }
MasaoHamanaka 0:a3a1d4768307 421 case NOTE_RA_CHAR: { key = KEY_A; score++; break; }
MasaoHamanaka 0:a3a1d4768307 422 case NOTE_SI_CHAR: { key = KEY_B; score++; break; }
MasaoHamanaka 0:a3a1d4768307 423 case NOTE_REST_CHAR:{ key = KEY_R; score++; break; }
MasaoHamanaka 0:a3a1d4768307 424 default:
MasaoHamanaka 0:a3a1d4768307 425 err = true;
MasaoHamanaka 0:a3a1d4768307 426 }
MasaoHamanaka 0:a3a1d4768307 427
Osamu Nakamura 1:cd3d332d4499 428 if (((KEY_A == key) && (OCTAVE_LEVEL_0 == octave)) ||
Osamu Nakamura 1:cd3d332d4499 429 ((KEY_B == key) && (OCTAVE_LEVEL_0 == octave))) {
MasaoHamanaka 0:a3a1d4768307 430 err = true;
MasaoHamanaka 0:a3a1d4768307 431 }
MasaoHamanaka 0:a3a1d4768307 432
MasaoHamanaka 0:a3a1d4768307 433 /* sharp */
MasaoHamanaka 0:a3a1d4768307 434 if (NOTE_SHARP == (*score)) {
MasaoHamanaka 0:a3a1d4768307 435 if (KEY_R == key) {
MasaoHamanaka 0:a3a1d4768307 436 err = true;
MasaoHamanaka 0:a3a1d4768307 437 } else {
MasaoHamanaka 0:a3a1d4768307 438 key++;
MasaoHamanaka 0:a3a1d4768307 439 score++;
MasaoHamanaka 0:a3a1d4768307 440 }
MasaoHamanaka 0:a3a1d4768307 441 }
MasaoHamanaka 0:a3a1d4768307 442
MasaoHamanaka 0:a3a1d4768307 443 /* pitch */
MasaoHamanaka 0:a3a1d4768307 444 if (isdigit(*score)) {
MasaoHamanaka 0:a3a1d4768307 445 pitch = ((*score++) - '0');
MasaoHamanaka 0:a3a1d4768307 446 if (isdigit(*score)) {
MasaoHamanaka 0:a3a1d4768307 447 pitch = (pitch * 10) + ((*score++) - '0');
MasaoHamanaka 0:a3a1d4768307 448 }
MasaoHamanaka 0:a3a1d4768307 449 } else {
MasaoHamanaka 0:a3a1d4768307 450 err = true;
MasaoHamanaka 0:a3a1d4768307 451 }
MasaoHamanaka 0:a3a1d4768307 452
MasaoHamanaka 0:a3a1d4768307 453 /* dotted */
MasaoHamanaka 0:a3a1d4768307 454 if (NOTE_DOT == (*score)) {
MasaoHamanaka 0:a3a1d4768307 455 dot = DOTTED_NOTE;
MasaoHamanaka 0:a3a1d4768307 456 score++;
MasaoHamanaka 0:a3a1d4768307 457 } else {
MasaoHamanaka 0:a3a1d4768307 458 dot = NOT_DOTTED_NONE;
MasaoHamanaka 0:a3a1d4768307 459 }
MasaoHamanaka 0:a3a1d4768307 460
MasaoHamanaka 0:a3a1d4768307 461 /* tie */
MasaoHamanaka 0:a3a1d4768307 462 if (NOTE_TIE == (*score)) {
MasaoHamanaka 0:a3a1d4768307 463 tie = TIED_NOTE;
MasaoHamanaka 0:a3a1d4768307 464 score++;
MasaoHamanaka 0:a3a1d4768307 465 } else {
MasaoHamanaka 0:a3a1d4768307 466 tie = NOT_TIED_NONE;
MasaoHamanaka 0:a3a1d4768307 467 }
MasaoHamanaka 0:a3a1d4768307 468
MasaoHamanaka 0:a3a1d4768307 469 /* set score */
MasaoHamanaka 0:a3a1d4768307 470 unit->score = score;
MasaoHamanaka 0:a3a1d4768307 471
MasaoHamanaka 0:a3a1d4768307 472 #ifdef UNIT_MSG
MasaoHamanaka 0:a3a1d4768307 473 snprintf(&unit->msg[0], UNIT_MSG - 1, "%d)%d%s%d -> %d/%d/%d\n",
MasaoHamanaka 0:a3a1d4768307 474 unit->channel,
MasaoHamanaka 0:a3a1d4768307 475 octave,
MasaoHamanaka 0:a3a1d4768307 476 note_name[key],
MasaoHamanaka 0:a3a1d4768307 477 pitch,
MasaoHamanaka 0:a3a1d4768307 478 note_timing[octave][key].tone,
MasaoHamanaka 0:a3a1d4768307 479 note_timing[octave][key].sfs,
MasaoHamanaka 0:a3a1d4768307 480 unit->speed / pitch);
MasaoHamanaka 0:a3a1d4768307 481 #endif /* UNIT_MSG */
MasaoHamanaka 0:a3a1d4768307 482
MasaoHamanaka 0:a3a1d4768307 483 if (!err) {
MasaoHamanaka 0:a3a1d4768307 484 /* set the sound volume */
MasaoHamanaka 0:a3a1d4768307 485 loud = (0 == note_timing[octave][key].sfs) ? (0): (unit->loudness);
MasaoHamanaka 0:a3a1d4768307 486 /* set */
MasaoHamanaka 0:a3a1d4768307 487 duration = unit->speed / pitch;
MasaoHamanaka 0:a3a1d4768307 488 if (dot) {
MasaoHamanaka 0:a3a1d4768307 489 duration += (duration >> 1);
MasaoHamanaka 0:a3a1d4768307 490 }
MasaoHamanaka 0:a3a1d4768307 491
MasaoHamanaka 0:a3a1d4768307 492 /* set next note or rest */
MasaoHamanaka 0:a3a1d4768307 493 unit->note.tone = note_timing[octave][key].tone;
MasaoHamanaka 0:a3a1d4768307 494 unit->note.sfs = note_timing[octave][key].sfs;
MasaoHamanaka 0:a3a1d4768307 495 unit->note.loud = loud;
MasaoHamanaka 0:a3a1d4768307 496 unit->note.attenuation = tie;
MasaoHamanaka 0:a3a1d4768307 497
MasaoHamanaka 0:a3a1d4768307 498 R_SDG_Tone(pianoT.unit[ch].channel, &pianoT.unit[ch].note);
MasaoHamanaka 0:a3a1d4768307 499 pianoT.unit[ch].count = duration;
MasaoHamanaka 0:a3a1d4768307 500 } else {
MasaoHamanaka 0:a3a1d4768307 501 pianoT.fin |= (1 << ch);
MasaoHamanaka 0:a3a1d4768307 502 }
MasaoHamanaka 0:a3a1d4768307 503
MasaoHamanaka 0:a3a1d4768307 504 /* marker */
MasaoHamanaka 0:a3a1d4768307 505 if (NOTE_MARKER == (*score)) {
MasaoHamanaka 0:a3a1d4768307 506 score++;
MasaoHamanaka 0:a3a1d4768307 507 value = 0;
MasaoHamanaka 0:a3a1d4768307 508 if (isdigit(*score)) {
MasaoHamanaka 0:a3a1d4768307 509 value = ((*score++) - '0');
MasaoHamanaka 0:a3a1d4768307 510 if (isdigit(*score)) {
MasaoHamanaka 0:a3a1d4768307 511 value = (value * 10) + ((*score++) - '0');
MasaoHamanaka 0:a3a1d4768307 512 }
MasaoHamanaka 0:a3a1d4768307 513 }
MasaoHamanaka 0:a3a1d4768307 514 unit->score = score;
MasaoHamanaka 0:a3a1d4768307 515
MasaoHamanaka 0:a3a1d4768307 516 if (NULL != pianoT.callback) {
MasaoHamanaka 0:a3a1d4768307 517 pianoT.callback(pianoT.unit[ch].channel, value);
MasaoHamanaka 0:a3a1d4768307 518 }
MasaoHamanaka 0:a3a1d4768307 519 }
MasaoHamanaka 0:a3a1d4768307 520 } else {
MasaoHamanaka 0:a3a1d4768307 521 pianoT.unit[ch].count--;
MasaoHamanaka 0:a3a1d4768307 522 }
MasaoHamanaka 0:a3a1d4768307 523 }
MasaoHamanaka 0:a3a1d4768307 524 }
MasaoHamanaka 0:a3a1d4768307 525
MasaoHamanaka 0:a3a1d4768307 526 /* End of File */