Synthesizer based on the Unzen / Nucleo F746ZG

Dependencies:   amakusa mbed-dsp mbed shimabara ukifune unzen_nucleo_f746

Fork of skeleton_unzen_nucleo_f746 by seiichi horie

雲仙フレームワークのテストとして作っているプロジェクトです。中身はどんどん変っていきます。 説明はDSP空挺団の「シンセサイザー」カテゴリーを参照してください。初回は「ドッグフードを食べる」です。

main.cpp

Committer:
shorie
Date:
2017-02-11
Revision:
28:547f19ed6f67
Parent:
26:e99f71165e19

File content as of revision 28:547f19ed6f67:

#include "mbed.h"

// Note : Do not touch the "unzen dependent" part. No need to read.
//        Modify the "project dependent" part.
//        Also, Modify the SignalProcessing class.


/************************** unzen dependent constants. ************************/
#define CODEC_I2C_ADDR 0x38 // Address of the ADAU-1361A


/*========================= Project Dependent Constants ======================*/
#define BLOCKSIZE 16        // number of the sample to be processed at once.
#define FS shimabara::Fs_48 // Fs can be Fs_32, Fs_441, Fs_48, Fs_96


/************************** unzen dependent include. **************************/
#include "unzen.h"          // audio framework include file
#include "umb_adau1361a.h"  // audio codec contoler include file
#include "amakusa.h"        // audio signal processing class library.
#include "ukifune.h"        // UI board support routines
#include "signal_processing.h"  // Implementaion of user signal processing.


/************************* Unzen Dependent Global Variables *******************/
    // I2C is essential to talk with ADAU1361
static I2C i2c(D14, D15);
    // create an audio codec contoler
static shimabara::UMB_ADAU1361A codec(FS, i2c, CODEC_I2C_ADDR );     
    // create an audio framework by singlton pattern
static unzen::Framework audio;
    // create a pointer to the signal processing object.
static SignalProcessing * process;


/************************* Unzen Dependent Function Prototype *****************/
    // for system usage. Do not care.
void initialize_system(void);
 

/*========================= Main program. ====================================*/
#define KEYCTRL( SWITCH, FREQ )\
        if ( pushing & ( 1 << ukifune::SWITCH ) )\
        {\
            process->set_vfo_frequency(FREQ);\
            process->eg_on();\
        }\
        else if ( releasing & ( 1 << ukifune::SWITCH ) )\
            process->eg_off();

int main() 
{    
    uint32_t pushing, releasing, holding;
    
        // VFO form
    wave_form form = triangle;
    
        // filter mode
    svf_mode filter_mode = lpf;

        // start audio. Do not touch
    initialize_system();
 
        // set tentative frequency   
    process->set_vfo_frequency( 440 );
    
        // set wave from
    process->set_vfo_wave_form( form );
    ukifune::turn_led_on( ukifune::led1_1 );
    ukifune::turn_led_off( ukifune::led1_2 );
 
        // set filter mode
    process->set_filter_mode( filter_mode );
    ukifune::turn_led_on( ukifune::led2_1 );
    ukifune::turn_led_off( ukifune::led2_2 );
    ukifune::turn_led_off( ukifune::led2_3 );
    ukifune::turn_led_off( ukifune::led2_4 );
        
 
       // main loop. Signal processing is done in background.
    while(1)     
    {       // place your foreground program here.

            // get volume from UI panel, then apply it to signal processing.
        process->set_volume( ukifune::get_volume(0) );  
        process->set_vfo_duty_cycle( ukifune::get_volume(1) ); 
        process->set_filter_f_factor( ukifune::get_volume(2) ); 
        process->set_filter_Q( ukifune::get_volume(3) ); 
        process->set_eg_attack( ukifune::get_volume(4) );   // A
        process->set_eg_decay( ukifune::get_volume(5) );    // D
        process->set_eg_sustain( ukifune::get_volume(6) );  // S
        process->set_eg_release( ukifune::get_volume(7) );  // R
       
            // sample usage of button switch detection
        ukifune::get_button_state( pushing, releasing, holding);

            // pushing detection demo
            // waveform
        if ( pushing & (1 << ukifune::swm1 ) )      // is SWM1 switch pusshing down?
            if  ( form == triangle )
            {
                form = square;
                process->set_vfo_wave_form( form );
                ukifune::turn_led_off( ukifune::led1_1 );
                ukifune::turn_led_on( ukifune::led1_2 );
            }
            else
            {
                form = triangle;
                process->set_vfo_wave_form( form );
                ukifune::turn_led_on( ukifune::led1_1 );
                ukifune::turn_led_off( ukifune::led1_2 );
            }
            
            // filter mode
        if ( pushing & (1 << ukifune::swm2 ) )      // is SWM2 switch pusshing down?
            if ( filter_mode == lpf )
            {
                filter_mode = bpf;
                process->set_filter_mode( filter_mode );    
                ukifune::turn_led_off( ukifune::led2_1 );
                ukifune::turn_led_on( ukifune::led2_2 );
                ukifune::turn_led_off( ukifune::led2_3 );
                ukifune::turn_led_off( ukifune::led2_4 );
            }
            else if ( filter_mode == bpf )
            {
                filter_mode = hpf;
                process->set_filter_mode( filter_mode );    
                ukifune::turn_led_off( ukifune::led2_1 );
                ukifune::turn_led_off( ukifune::led2_2 );
                ukifune::turn_led_on( ukifune::led2_3 );
                ukifune::turn_led_off( ukifune::led2_4 );
            }
            else // hpf
            {
                filter_mode = lpf;
                process->set_filter_mode( filter_mode );    
                ukifune::turn_led_on( ukifune::led2_1 );
                ukifune::turn_led_off( ukifune::led2_2 );
                ukifune::turn_led_off( ukifune::led2_3 );
                ukifune::turn_led_off( ukifune::led2_4 );
            }


            // Key board control
        KEYCTRL( swk1, 261.626 )
        KEYCTRL( swk2, 277.183 )
        KEYCTRL( swk3, 293.665 )
        KEYCTRL( swk4, 311.123 )
        KEYCTRL( swk5, 329.628 )
        KEYCTRL( swk6, 349.228 )
        KEYCTRL( swk7, 369.994 )
        KEYCTRL( swk8, 391.995 )
        KEYCTRL( swk9, 415.305 )
        KEYCTRL( swk10, 440.000 )
        KEYCTRL( swk11, 466.164 )
        KEYCTRL( swk12, 498.883 )
        KEYCTRL( swk13, 523.251 )
            
       
            // you have to call tick() every 20mS-50mS if you need get_volume()
        wait(0.05);
        ukifune::tick();
    }
}   // End of main


/************************* Unzen Dependent Callbacks **************************/
   // customer signal processing initialization call back.
void init_callback(
           unsigned int block_size     // block size [sample]
           )
{
       // place initialization code here
    process = new SignalProcessing( block_size );
}   // end of init_callback
 
 
   // customer signal processing call back.
void process_callback(
           float rx_left_buffer[],     // array of the left input samples
           float rx_right_buffer[],    // array of the right input samples
           float tx_left_buffer[],     // place to write the left output samples
           float tx_right_buffer[],    // place to write the right output samples
           unsigned int block_size     // block size [sample]
           )
{
       // place signal processing code here
    process->run( rx_left_buffer, rx_right_buffer, tx_left_buffer, tx_right_buffer, block_size );
}   // End of process_callback


/************************* Unzen Dependent Function implementation ************/
void initialize_system(void)
{
        // Set I3C clock to 100kHz
    i2c.frequency( 100000 );
 
        // Configure the optional block size of signal processing. By default, it is 1[Sample] 
    audio.set_block_size(BLOCKSIZE);

        // Start UI module.
    ukifune::init( & audio );
   
        // Start the ADAU1361. Audio codec starts to generate the I2C signals 
    codec.start();
        // Start the audio framework on ARM processor.  
    audio.start( init_callback, process_callback);     // path the initializaiton and process call back to framework 
 
        // Setup initial analog gain   
    codec.set_hp_output_gain( 0, 0 );
    codec.set_line_output_gain( 0, 0 );
}