以前のLibraryでは、スピーカ出力にPWM,DigitalOutを使いましたが、これは、両方ともPWMにしたものです。LPC1114FN28ではDigitalOutにノイズが乗ることがありその対応です。

Dependents:   kitchenTimer LPC1114FN28_kitchenTimer_Clock

Fork of Sound by suu pen

Sound.cpp

Committer:
suupen
Date:
2013-11-10
Revision:
15:7e1945a135d7
Parent:
14:027fe57d3491

File content as of revision 15:7e1945a135d7:

/***********************************************************************/
/*                                                                     */
/*    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.write(0.0);  //@SS131027
//@SS131027    _kijun = 0; //@SS131027


    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){

    if(siji != 0){
        // siji no atai wo fugo ga minus no toki hanten
         if(fugo == 1){siji = 1.0 - siji;}
         _kijun.write((float)fugo);    //@SS131027
//@SS131027    _kijun = fugo;  //@SS131027
      
        _pwm.write(siji);   // 2tuizyo sound out settei site ,interrupt no nakade renzoku de pwm set wo suruto bousou suru.
    }
    else{                       //@SS131110
        // sound off            //@SS131110
        _kijun.write(0.0);      //@SS131110
        _pwm.write(0.0);        //@SS131110
 
   }
}
/*****************************************
* 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
//131020const float DT_onkaiHzN[3][7] = {//    C1              D1          E1          F1          G1          A1          B1        // frequency (1/1 [Hz]/count)  //131020
const float DT_onkaiHzN[3][7] = {//    C1              D1          E1          F1          G1          A1          B1        // frequency (1/1 [Hz]/count)          //131020
                                    {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)
//131020        O_sound.syuuki = 1000000 / (DT_onkaiHzN[data.hanon][kaicho] * (pow(2.0, ((double)okutabu - 1))));           //131020
                O_sound.syuuki = 1000000 / (uint16_t)(DT_onkaiHzN[data.hanon][kaicho] * (pow(2.0, ((double)okutabu - 1)))); //131020
                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) {
   const sound_t END_DATA[] =     {                                             //@SS131110
    //   hanon siji 0:b(flat)   1:tujo  2:#(sharp)                              //@SS131110
    //   |  C1 - B9 kan deno onkai(Gx ha 9x ni okikae te siji)  0xFF=end data   //@SS131110
    //   |  |   time (1/1[ms]/count)                                            //@SS131110
    //   |  |   |    envelope(yoin) (1/1 [ms]/count)                            //@SS131110
    //   |  |   |    |                                                          //@SS131110
        {1,0xFF,0000,0}   // end                                                //@SS131110
    };                                                                          //@SS131110

    sound_t data;                                                               //@SS131110
    
    // enso data settei
    if((sound_sound() == false)     // oto no syuturyoku jikan hantei
    & (onpu != NULL)                // enso chu ka wo kakunin
     ){
        // tugi no onpu data syutoku
//@SS131110        sound_t data = *onpu;                                        //@SS131110
        data = *onpu;                                                           //@SS131110
        if(data.onkai == 0xff){
            sound_sound(data);      //131026
            onpu = NULL;
        }
        else{
            // tugi no hatuon siji
            sound_sound(data);
            onpu++;
        }
    
    }
    else if(onpu == NULL){                                                      //@SS131110
        data = *END_DATA;                                                       //@SS131110
        sound_sound(data);                                                      //@SS131110
    }                                                                           //@SS131110

}




/******************************************************************************
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
    };
*/