Wave Table Synthesizer(Occilator only). I will make Envelope Generator and MML for play music.

Dependencies:   mbed

Project: Synthesizer. It is using embed to Chip Tune Synthesizer for NXP LPC1768.

At First

Prepare an amplifier with volume wheel. The amplifier wire at pin1 to pin18(D/A converter) from IC Clip or Breedboard.

Play

Check out this project and deploy your mbed. And then push the reset key.

You hear a sound from amplifier.

Modify

First step, you can see main.cpp. This source file plays an occilator with "wait()". Modify frequency at

#define ADD 0x2000000

on the top of source.

Occilator select 7 waveforms.

  • OCC_NONE,
  • OCC_SQUARE,
  • OCC_SINE,
  • OCC_SAW,
  • OCC_WT,
  • OCC_NOISE,
  • OCC_TRIANGLE,

WT means WaveTable Synthesizer.Use "setWave()" function at first.Wavetable will copy in instance.

Change there for waveform.

    gOccilator[0]=Occilator::getInstance(OCC_SAW,INTERRUPT_TIME_US);

INTERRUPT_TIME_US depends sampling rate. Don't change.

Total volume of D/A converter is setting this place.

        gOccilator[0]->setVolume(volume);

By the way, this sample output 0 to 1V(not3.3V) for deforming distortion.

ToDo

  • Envelope generator and LFO(with delay)
  • MML(Music Macro Language)
  • Sample Song(I will make a Japanese Anime music,perhaps)

Project Goal Date

I will make for Comic Market 90(2016.Aug. in Tokyo).And these thing will be written in a Doujinshi.

Occilator.cpp

Committer:
117Florian
Date:
2016-02-10
Revision:
10:40bed7449a81
Parent:
9:d2a5406650ae

File content as of revision 10:40bed7449a81:

#include "mbed.h"
#include "global.h"
#include "Occilator.h"
#include "Square.h"
#include "WT.h"
#include "Sine.h"
#include "Noise.h"
#include "Saw.h"
#include "Triangle.h"

static long interrupt_us;
static int part_num=0;
static Occilator* part[OCCILATOR_PART_NUM];
static Ticker sTicker;
static long total_value_in_this_span;
static AnalogOut sAnalogOut(p18);
static long sMasterVolume=(1/3.3)*0x10000;

/* interrupt handler */
/*static void tick(uint32_t id);*/
static void tick();

Occilator* Occilator::getInstance(Occilator_Type type,long interrupt_us)
{
    switch(type)
    {
        case OCC_NONE:
        case OCC_SQUARE:
            return new Square(interrupt_us);

        case OCC_NOISE:
            return new Noise(interrupt_us);
            
        case OCC_SINE:
            return new Sine(interrupt_us);
            
        case OCC_SAW:
            return new Saw(interrupt_us);
            
        case OCC_TRIANGLE:
            return new Triangle(interrupt_us);
        case OCC_WT:
        default:
            return new WT(interrupt_us);
        
    }
}

void Occilator::setMasterVolume(long volume)
{
    sMasterVolume=volume;
}

Occilator::Occilator(long interrupt_us)
{
    myled1=1;
    ::interrupt_us=interrupt_us;
    if(part_num==0)
    {
        sTicker.attach_us(::tick,interrupt_us);
    }
    part_num++;
    for(int i=0;i<OCCILATOR_PART_NUM;i++)
    {
        if(part[i]==NULL)
        {
            part[i]=this;
            break;
        }
    }
    
    m_Volume=0x10000;
}

Occilator::~Occilator()
{
    part_num--;
    for(int i=0;i<OCCILATOR_PART_NUM;i++)
    {
        if(part[i]==this)
        {
            part[i]=NULL;
            break;
        }
    }
    if(part_num<=0)
    {
        sTicker.detach();
    }
}

void Occilator::setOmega(long speed)
{
    m_Omega=speed;
    myled2=1;
}

void Occilator::setVolume(int volume)
{
    m_Volume=volume;
}

unsigned long Occilator::tick()
{
    m_Angle+=m_Omega;
    return 0L;
}

void ::tick()
{
    long long value=0;

    for (int i=0;i<OCCILATOR_PART_NUM;i++)
    {
        if (part[i]!=NULL)
        {
            value+=total_value_in_this_span + part[i]->tick();
        }
    }
    value = value>=0x10000 ? 0xffff : value;
    value = (sMasterVolume*value)>>16;
    sAnalogOut.write_u16(value);
    myled4=value > 0x80000000;
}