CURRENT ISSUE

Contests

bottom corner

Feature Article



Issue #207 October 2007
Embedded Speech
Speech Synthesis for Small Applications

by Nicusor Birsan & Ionut Tarsa

Start | Embedding Speech | Speech Synthesis Techniques | Open-Source Project | System Building Blocks | Sound From Luminary Micro | First Big Porting Problem | Synthesizer | Translator | The LM3S811 Speaks | More Speech Applications | Sources & PDF

Listing 1—While playback is done from one half of the buffer, the other half is filled with data.


//internal driver buffer
#define MAXIM_BUF 1024
unsigned char* MCU_out_ptr;
unsigned char* MCU_out_end;
unsigned char  MCU_outbuf[MAXIM_BUF];
//=================================================================
// Sound Handler
// Output samples to PWM1
// if max_ix is reached the generation is stoped
//=================================================================
void IntSoundHdl(void) {
    unsigned short m_ind = snd_ix;
    //use a register as apointer to SFRs
    unsigned long* p_gen = (unsigned long*) TIMER0_BASE;
    p_gen[((TIMER_O_ICR)/4)] =  TIMER_TIMA_TIMEOUT;
    if(m_ind != max_ix){
        unsigned long c =  MCU_outbuf[m_ind++]+5;
        snd_ix = m_ind & (MAXIM_BUF -1);
        p_gen = (unsigned long*) (PWM_BASE + PWM_GEN_1);
        p_gen[((PWM_O_X_CMPA)/4)] = c;
        p_gen[((PWM_O_X_CMPB)/4)] = c;
    }else{
        //stop generation (disable timer interrupt)
        HWREG(NVIC_DIS0) =  1 << (INT_TIMER0A - INT_GPIOA);
        sound_stopped = 1;  
    }
}
void task_sound_driver(void){
    static unsigned short prev_ix=0;
    unsigned short curr_ix = snd_ix & (MAXIM_BUF/2);
    if( (curr_ix != prev_ix) ){
                // driver is playing, fill next half buffer only
        MCU_out_ptr = MCU_outbuf + prev_ix;
        MCU_out_end = MCU_out_ptr + (MAXIM_BUF/2-1);
        filled = MCU_WavegenFill(0);
    }
}

 


bottom corner