このライブラリでは、単音とメロディの出力が可能です。 In this library, you can output a single tone and melody. mbedのpwmOutとDigitalOutを使ってスピーカや圧電ブザーを直接駆動します。 directly drive speaker or buzzer and DigitalOut pwmOut using the mbed. メロディデータは、mbedのローカルにtxtファイルとして保存するか、プログラム中に配列データとして保存してください。 Melody data is either stored in a txt file on the local mbed, save it as a data array in the program.
Dependents: kitchenTimer_Clock SoundLibraryExample_Melody_ProgramData M3PI_SuiviLigne
Revision 0:e3f005984c2a, committed 2011-11-16
- Comitter:
- suupen
- Date:
- Wed Nov 16 12:03:27 2011 +0000
- Child:
- 1:358449cfdcd3
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sound.cpp Wed Nov 16 12:03:27 2011 +0000 @@ -0,0 +1,453 @@ +/***********************************************************************/ +/* */ +/* Sound.cpp */ +/* */ +/* pwmOutput - digtalOutput de sound syuturyoku suru library */ +/***********************************************************************/ +#define _SOUND_C + +#include "types.h" +#include "mbed.h" +#include "math.h" +#include "Sound.h" + +LocalFileSystem local("local"); + +/******************************************************************* +* syokika +*******************************************************************/ +Sound::Sound(PinName pwm, PinName kijun) : _pwm(pwm), _kijun(kijun){ + /*********************** + * kido ji no yobidasi + ***********************/ + sound_timer.attach_us(this, &Sound::pulseCheck, Z_pulseCheckSyuuki); // oto no hakei syuturyoku check time + + hatuon_jikan.start(); // 1tu no oto no hatuon jikan kakunin + + _pwm.period_us(Z_pwmSyuuki); + + _pwm.write(0.0); + _kijun = 0; + + + keikajikan = 0; // 1tu no oto no keikajikan + + F_pwmSet = 0; // 0:zenhan hansyuuki 1:kohan hansyuuki wo request + C_syuukiKeika = 0; + f_muonSet = 0; // muon ji no sound_out() syori wo kurikaesu no wo fusegu + +} + + + +/***************************************** +* analog output +* siji : syuturyoku siji (0.0 - 1.0) absolute +* fugo : syuturyoku fugo 0:+ 1:- +*****************************************/ +void Sound::sound_out(float siji, int8_t fugo){ + + // siji no atai wo fugo ga minus no toki hanten + if(fugo == 1){siji = 1.0 - siji;} + _kijun = fugo; + + _pwm.write(siji); // 2tuizyo sound out settei site ,interrupt no nakade renzoku de pwm set wo suruto bousou suru. + +} +/***************************************** +* sound hakei pwm output +* time interrupt +*****************************************/ +void Sound::pulseCheck(void) { + +// uint32_t static C_syuukiKeika = 0; +// uint8_t static f_muonSet = 0; // muon ji no sound_out() syori wo kurikaesu no wo fusegu +// uint8_t static F_pwmSet = 0; // 0:zenhan hansyuuki 1:kohan hansyuuki wo request + + float D_soundOut; // syuturyoku suru sinpuku chi (0.0 - 1.0) + + if (O_sound.syuuki != 0) { + f_muonSet = 1; + // sound ari + if (C_syuukiKeika < (O_sound.syuuki / 2.0)) { + // zenhan han syuuki + if (F_pwmSet == 0) { + F_pwmSet = 1; + + D_soundOut = (float)pow(((double)O_sound.envelope / O_sound.shokichienvelope), 2.0); + sound_out(D_soundOut, 0); + } + C_syuukiKeika += Z_pulseCheckSyuuki; + } else if (C_syuukiKeika < O_sound.syuuki) { + // kohan han syuuki + if (F_pwmSet == 1) { + F_pwmSet = 2; + + D_soundOut = (float)pow(((double)O_sound.envelope / O_sound.shokichienvelope) , 2.0); + sound_out(D_soundOut, 1); + } + C_syuukiKeika += Z_pulseCheckSyuuki; + + + } else { + // jikai syuuki settei + F_pwmSet = 0; + C_syuukiKeika = 0; + } + + // envelope jikan no kosin + if (O_sound.envelope > Z_pulseCheckSyuuki) { + O_sound.envelope -= Z_pulseCheckSyuuki; + } else { + O_sound.envelope = 0; + } + } + else{ + // O_sound.syuuki == 0 then sound nasi + + if(f_muonSet == 0){ + f_muonSet = 1; + sound_out(0.0, 0); // 5us + } + } + + //************************************************* + // 1ms syuuki syori + //************************************************* + C_1msProcess++; + if((C_1msProcess * Z_pulseCheckSyuuki) > 1000){ + C_1msProcess = 0; + sound_ensoSyori(); + } +} + + +/****************************************************************************** +Name : sound_sound() +Parameters : sound_t .hanon + : .onkai + : .time : hatuon jikan(1/1 [ms]/count) + : .envelope : yoin (1/1 [ms]/count) +Returns : none +Description : hitotu no oto no syuturyoku +******************************************************************************/ +//************************* +// oto jyotai check +// ture : oto ari chu +// false: oto nasi chu +//************************* +bool Sound::sound_sound(void){ + if (hatuon_jikan.read_ms() < keikajikan){ + return(true); + } + else{ + return(false); + } +} + +//************************* +// oto syuturyoku +//************************* +void Sound::sound_sound(sound_t data) { + + uint8_t onkai; + uint8_t okutabu; + uint8_t kaicho; + +// oto no frequency // do re mi fa so ra si +const uint16_t DT_onkaiHzN[3][7] = {// C1 D1 E1 F1 G1 A1 B1 // frequency (1/1 [Hz]/count) + {30.8677, 34.6478, 38.8909, 41.2034, 46.2493, 51.9131, 58.2705}, // b + {32.7032, 36.7081, 41.2034, 43.6535, 48.9994, 55.0000, 61.7354}, // nomal + {34.6478, 38.8909, 43.6535, 46.2493, 51.9131, 58.2705, 65.4064}, // # + }; + + + // onkai data kara DT_onkaiHzN[][koko] "koko" no number ni henkan + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F + const uint8_t DT_onkaiTrans[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 1, 2, 3}; + + + // tugi no hatuon siji + onkai = data.onkai; + + okutabu = onkai & 0x0f; + kaicho = DT_onkaiTrans[(onkai & 0xf0) >> 4]; + + switch (onkai) { + case 0x00: + // enso chu (tugi no hatuon nasi settei) + // case 0xff to onaji syori + case 0xff: + // enso syuryo + O_sound.syuuki = 0; // muon + break; + default: + // enso chu & tugi no hatuon settei) + O_sound.syuuki = 1000000 / (DT_onkaiHzN[data.hanon][kaicho] * (pow(2.0, ((double)okutabu - 1)))); + O_sound.envelope = data.envelope * 1000; + O_sound.shokichienvelope = data.envelope * 1000; + break; + } + + // oto no syuturyoku jikan timer restart + hatuon_jikan.reset(); + keikajikan = data.time; +} + +/****************************************************************************** +Name : sound_ensoSyori() +Parameters : none +Returns : none +Description : enso ji no tugino onpu data syutoku +******************************************************************************/ +void Sound::sound_ensoSyori(void) { + + // enso data settei + if((sound_sound() == false) // oto no syuturyoku jikan hantei + & (onpu != NULL) // enso chu ka wo kakunin + ){ + // tugi no onpu data syutoku + sound_t data = *onpu; + if(data.onkai == 0xff){ + onpu = NULL; + } + else{ + // tugi no hatuon siji + sound_sound(data); + onpu++; + } + + } + +} + + + + +/****************************************************************************** +Name : sound_enso() +Parameters : - +Returns : - +Description : - +******************************************************************************/ +//*********************************************************** +// load enso data(mbed drive) +// Parameter : "/local/enso.txt" (data name = enso.txt) +//*********************************************************** +bool Sound::sound_enso(char *path) { + int32_t ans; + + // file open + FILE *stm = fopen(path,"r"); + if(stm == NULL){ + return (false); + } + + // enso data set + uint8_t i = 0; + do{ + ans = fscanf(stm, "%x%d%d", &enso[i].onkai, &enso[i].time, &enso[i].envelope); + i++; + + }while((ans != EOF) & (i < 100)); + + fclose(stm); + + ensoDataTable = enso; + + return (true); +} + +//*********************************************************************** +// load enso data(program data table) +// Parameter : (Sound::sound_t*)DEMEKIN (data table name = DEMEKIN) +//*********************************************************************** +void Sound::sound_enso(Sound::sound_t* onpudata) { + ensoDataTable = onpudata; +} + + +//************************* +// enso jyotai check +// ture : enso chu +// false: enso syuryo +//************************* +bool Sound::sound_enso(void) { + bool ans; + + if(onpu != NULL){ + ans = true; + } + else{ + ans = false; + } + return (ans); +} + +//******************* +// enso start / stop +// true : start +// false: stop +//******************* +void Sound::sound_enso(bool siji){ + if(siji == true){ + onpu = (sound_t*)ensoDataTable; + } + else{ + onpu = NULL; + } +} + + + + + +/****************************************************************************** +Name : enso data sample +Parameters : - +Returns : - +Description : - +******************************************************************************/ +/* +//------------------------------ +// "demekin no uta" merody data +//------------------------------ + const sound_t DEMEKIN[] = { + // onkai,hatuon jikan[ms] + {1,0xC5,600,500}, // de + {1,0xE5,600,500}, // me + {1,0x95,600,500}, // kin + {1,0x00,600,500}, + + {1,0xC5,600,500}, // de + {1,0xE5,600,500}, // me + {1,0x95,600,500}, // kin + {1,0x00,600,500}, + + {1,0xC5,600,500}, // de + {1,0xE5,600,500}, // me + {1,0x95,600,500}, // kin + {1,0x95,600,500}, // no + {1,0x95,150,500}, // shi + {1,0x00,900,500}, + {1,0xE5,750,500}, // po + {1,0x00,450,500}, + + {1,0xC5,600,500}, // de + {1,0xE5,600,500}, // me + {1,0x95,600,500}, // kin + {1,0x00,600,500}, + + {1,0xC5,600,500}, // de + {1,0xE5,600,500}, // me + {1,0x95,600,500}, // kin + {1,0x00,600,500}, + + {1,0x95,600,500}, // ju + {1,0xE5,600,500}, // go + {1,0xD5,600,500}, // n + {1,0xC5,600,500}, // no + {1,0xE5,150,500}, // shi + {1,0x00,900,500}, + {1,0xC5,750,500}, // po + {1,0x00,1350,500}, + + {1,0xFF,0,0}, // end + + }; + +//--------------------------------- +// "westminster chime" merody data +//--------------------------------- + const sound_t WESTMINSTER[] = { + // onkai,hatuon jikan[ms] + {1,0xA4,1200,1000}, + {1,0xF4,1200,1000}, + {1,0x94,1200,1000}, + {1,0xC4,2400,1000}, + + {1,0xC4,1200,1000}, + {1,0x94,1200,1000}, + {1,0xA4,1200,1000}, + {1,0xF4,2400,1000}, + + + {1,0xFF,0,0}, // end + }; + +//------------------------------ +// "ramen chime" merody data +//------------------------------ + const sound_t RAMEN[] = { + // onkai,hatuon jikan[ms] + {1,0xC5,300,500}, + {1,0xD5,300,500}, + {1,0xE5,1200,500}, + {1,0xD5,600,500}, + {1,0xC5,1200,500}, + + {1,0xC5,300,500}, + {1,0xD5,300,500}, + {1,0xE5,300,500}, + {1,0xD5,300,500}, + {1,0xC5,300,500}, + {1,0xD5,1800,500}, + + + {1,0xFF,0,0}, // end + }; +*/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sound.h Wed Nov 16 12:03:27 2011 +0000 @@ -0,0 +1,187 @@ +/***********************************************************************/ +/* */ +/* Sound.h */ +/* */ +/* V0.1 : 2011/11/13 */ +/***********************************************************************/ +#ifndef _SOUND_H +#define _SOUND_H + +#include <string> +#include "types.h" + + +/** Sound output control class, based on a PwmOut +* +* Example: +* @code +* // Continuously sweep the servo through it's full range +* +*#include "mbed.h" +*#include "pwmSound.h" // pwm sound library header +* +*Sound sound(p21, p10); // 1tu me no sound syuturyoku (pwmOut = p21, digitalOut = p10) +* +* //-------------------------------- +* // "westminster chime" merody data +* //-------------------------------- +* const Sound::sound_t WESTMINSTER[] = { +* // hanon siji 0:b(flat) 1:tujo 2:#(sharp) +* // | C1 - B9 kan deno onkai(Gx ha 9x ni okikae te siji) 0xFF=end data +* // | | time (1/1[ms]/count) +* // | | | envelope(yoin) (1/1 [ms]/count) +* // | | | | +* {1,0xA4,1200,1000}, +* {1,0xF4,1200,1000}, +* {1,0x94,1200,1000}, +* {1,0xC4,2400,1000}, +* +* {1,0xC4,1200,1000}, +* {1,0x94,1200,1000}, +* {1,0xA4,1200,1000}, +* {1,0xF4,2400,1000}, +* +* {1,0xFF,1000,0}, // end +* }; +* +* /-------------------------------------- +** main +* /--------------------------------------- +*int main() { +* +* //--------------------- +* // enso data no settei +* //--------------------- +* // sound.sound_enso("/local/enso.txt"); // mbed local file data "enso.txt" load (sita ni data no rei wo oite oku) +* sound.sound_enso((Sound::sound_t*)DEMEKIN); +* +* while(1) { +* +* //--------------------------------------------------- +* // tanon syuturyoku no ato ni westminster chime enso +* //--------------------------------------------------- +* if(sound.sound_enso() == false){ +* //sound2.sound_enso((Sound::sound_t*)RAMEN); +* +* +* // tanon1 +* Sound::sound_t oto = {1,0x95,200,100}; +* sound.sound_sound(oto); +* while(sound.sound_sound() == true){} +* +* // tanon2 +* oto.hanon = 1; oto.onkai = 0xA5; oto.time = 2000; oto.envelope = 1000; +* sound.sound_sound(oto); +* while(sound.sound_sound() == true){} +* +* // sai enso +* sound.sound_enso(true); +* } +* } +*} +* +* @endcode +*/ + + + + + + + + + + + + + + +class Sound { +public: + + +typedef struct { + uint8_t hanon; // hanon siji 0:b(flat) 1:tujo 2:#(sharp) + uint16_t onkai; // C1 - B9 kan deno onkai(Gx ha 9x ni okikae te siji) + // 0x00:hatuon teisi 0xFF:enso syuryo + uint16_t time; // hatuon jikan (1/1 [ms]/count) + uint16_t envelope; // yoin(envelope) jikan (1/1 [ms]/count) +} sound_t; + +/* +// hanon no menber +enum{ + Z_hanonF = 0, // b + Z_hanonN , // tujo + Z_hanonS, // # +}; +*/ + + /** Create a sound object connected to the specified PwmOut pin & DigitalOut pin + * + * @param pin PwmOut pin to connect to + * @param pin DigitalOut pin to connect to + */ + Sound(PinName pwm , PinName kijun); + + /** Check sound output + * + * @param return A bool ture : output\\false: none + */ + bool sound_sound(void); // oto no syuturyoku jotai wo kakunin + // true : oto ari false : oto nasi + void sound_sound(sound_t data); // oto no syuturyoku + // para : oto no data + + bool sound_enso(char *path); // enso data wo file kara yomikomi + // true : data kakunou OK false: data kakunou NG + void sound_enso(Sound::sound_t* onpudata); // enso data wo program no data table kara yomikomi + bool sound_enso(void); // enso jyotai check + // true : enso chu false : enso shuryo + void sound_enso(bool siji); // enso start / stop + // true : enso start false : enso stop + +//protected: +private: + PwmOut _pwm; + DigitalOut _kijun; + + Ticker sound_timer; + Timer hatuon_jikan; + + +#define Z_pwmSyuuki (1) // PWM syuuki (1/1[us]/count) syokichi = 1 +#define Z_pulseCheckSyuuki (20) // puls check syuuki (1/1 [us]/count) syokichi = 20 (10us ika deha pwm settei ga ijo ni naru) + + +typedef struct{ + uint32_t syuuki; // oto no syuuki no count suu wo kioku (1/1 [us]/count) + uint32_t jikan; // oto no syuturyoku jikan wo kanri (1/1 [us]/count) + uint32_t envelope; // envelope counter 0 - 1000000[us](1[s]) + uint32_t shokichienvelope; // shokichi envelope counter 0 - 1000000[us](1[s]) +} soundout_t; + + +soundout_t O_sound; // oto no syuturyoku pwm data + +sound_t enso[100]; // mbed drive no enso data kakuno yo +sound_t *ensoDataTable; // enso data no sento address kioku + + void sound_out(float siji, int8_t fugo); + void pulseCheck(void); + uint8_t F_pwmSet; // 0:zenhan hansyuuki 1:kohan hansyuuki wo request + uint32_t C_syuukiKeika; + uint8_t f_muonSet; // muon ji no sound_out() syori wo kurikaesu no wo fusegu + uint32_t C_1msProcess; // 1ms syuuki syori counter (Z_pulseCheckSyuuki/1 [us]/count)) + + + void sound_ensoSyori(void); + int keikajikan; // 1tu no oto no keikajikan + sound_t* onpu; // onpu data no sento address + + +}; + + +#undef _SOUND_C +#endif // _SOUND_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/types.h Wed Nov 16 12:03:27 2011 +0000 @@ -0,0 +1,114 @@ +/*----------------------------------------------------------------------------*/ +/* File Information */ +/*----------------------------------------------------------------------------*/ +/* Name : types.h */ +/* Type : C Programming Language Header */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ + +#ifndef __TYPES_H__ +#define __TYPES_H__ + +#include "stdint.h" +/* +typedef char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +*/ +//typedef bool bool_t; +typedef enum{TRUE, FALSE} bool_t; + +//========================================================================= +// byte bit access +//========================================================================= +typedef union{ // BYTE�^(BYTE/NIBBLE/BIT access) + uint8_t byte; // Byte access + struct{ // Nibble���� + uint8_t lo : 4; // lower(Bit0 - 3) + uint8_t hi : 4; // upper(Bit4 - 7) + }nibble; + struct{ // Bit access + uint8_t b0 : 1; // Bit0 + uint8_t b1 : 1; // Bit1 + uint8_t b2 : 1; // Bit2 + uint8_t b3 : 1; // Bit3 + uint8_t b4 : 1; // Bit4 + uint8_t b5 : 1; // Bit5 + uint8_t b6 : 1; // Bit6 + uint8_t b7 : 1; // Bit7 + }bits; +}byte_t; + +//========================================================================= +// word bit access +//========================================================================= +typedef union{ // WORD�^(WORD/BYTE/NIBBLE/BIT access) + uint16_t word; // Word access + struct{ // Byte access + uint8_t b0; // upper byte + uint8_t b1; // lower byte + }byte; + struct { // Nibble access + uint8_t n0 : 4; // lower byte low(Bit 0 - 3) + uint8_t n1 : 4; // lower byte up (Bit 4 - 7) + uint8_t n2 : 4; // upper byte low(Bit 8 - 11) + uint8_t n3 : 4; // upper byte up (Bit12 - 15) + }nibble; + struct{ // Bit acces + uint8_t b0 : 1; // Bit0 + uint8_t b1 : 1; // Bit1 + uint8_t b2 : 1; // Bit2 + uint8_t b3 : 1; // Bit3 + uint8_t b4 : 1; // Bit4 + uint8_t b5 : 1; // Bit5 + uint8_t b6 : 1; // Bit6 + uint8_t b7 : 1; // Bit7 + uint8_t b8 : 1; // Bit8 + uint8_t b9 : 1; // Bit9 + uint8_t b10: 1; // Bit10 + uint8_t b11: 1; // Bit11 + uint8_t b12: 1; // Bit12 + uint8_t b13: 1; // Bit13 + uint8_t b14: 1; // Bit14 + uint8_t b15: 1; // Bit15 + }bits; +}word_t; + + +//========================================================================= +// ascii code +//========================================================================= +#define Z_NUL (0x00) +#define Z_SOH (0x01) +#define Z_STX (0x02) +#define Z_ETX (0x03) +#define Z_EOT (0x04) +#define Z_ENQ (0x05) +#define Z_ACK (0x06) +#define Z_BEL (0x07) + +#define Z_BS (0x08) +#define Z_HT (0x09) +#define Z_LF (0x0A) +#define Z_HM (0x0B) +#define Z_FF (0x0C) +#define Z_CR (0x0D) +#define Z_SO (0x0E) +#define Z_SI (0x0F) + +#define Z_DLE (0x10) +#define Z_DC1 (0x11) +#define Z_DC2 (0x12) +#define Z_DC3 (0x13) +#define Z_DC4 (0x14) +#define Z_NAK (0x15) +#define Z_SYN (0x16) +#define Z_ETB (0x17) + + +#endif /* __TYPES_H__*/