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.

Committer:
117Florian
Date:
Wed Feb 10 10:55:08 2016 +0000
Revision:
10:40bed7449a81
Parent:
9:d2a5406650ae
Adjust volume saw.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
117Florian 3:32094530d55e 1 #include "mbed.h"
117Florian 3:32094530d55e 2 #include "global.h"
117Florian 3:32094530d55e 3 #include "Occilator.h"
117Florian 4:2febde858269 4 #include "Square.h"
117Florian 7:a478d5cc411e 5 #include "WT.h"
117Florian 8:dd2da7c0c4c7 6 #include "Sine.h"
117Florian 8:dd2da7c0c4c7 7 #include "Noise.h"
117Florian 8:dd2da7c0c4c7 8 #include "Saw.h"
117Florian 9:d2a5406650ae 9 #include "Triangle.h"
117Florian 3:32094530d55e 10
117Florian 3:32094530d55e 11 static long interrupt_us;
117Florian 3:32094530d55e 12 static int part_num=0;
117Florian 3:32094530d55e 13 static Occilator* part[OCCILATOR_PART_NUM];
117Florian 3:32094530d55e 14 static Ticker sTicker;
117Florian 3:32094530d55e 15 static long total_value_in_this_span;
117Florian 3:32094530d55e 16 static AnalogOut sAnalogOut(p18);
117Florian 5:3a753cf68fac 17 static long sMasterVolume=(1/3.3)*0x10000;
117Florian 3:32094530d55e 18
117Florian 3:32094530d55e 19 /* interrupt handler */
117Florian 3:32094530d55e 20 /*static void tick(uint32_t id);*/
117Florian 3:32094530d55e 21 static void tick();
117Florian 3:32094530d55e 22
117Florian 4:2febde858269 23 Occilator* Occilator::getInstance(Occilator_Type type,long interrupt_us)
117Florian 4:2febde858269 24 {
117Florian 4:2febde858269 25 switch(type)
117Florian 4:2febde858269 26 {
117Florian 4:2febde858269 27 case OCC_NONE:
117Florian 4:2febde858269 28 case OCC_SQUARE:
117Florian 4:2febde858269 29 return new Square(interrupt_us);
117Florian 8:dd2da7c0c4c7 30
117Florian 8:dd2da7c0c4c7 31 case OCC_NOISE:
117Florian 8:dd2da7c0c4c7 32 return new Noise(interrupt_us);
117Florian 4:2febde858269 33
117Florian 4:2febde858269 34 case OCC_SINE:
117Florian 8:dd2da7c0c4c7 35 return new Sine(interrupt_us);
117Florian 8:dd2da7c0c4c7 36
117Florian 8:dd2da7c0c4c7 37 case OCC_SAW:
117Florian 8:dd2da7c0c4c7 38 return new Saw(interrupt_us);
117Florian 9:d2a5406650ae 39
117Florian 9:d2a5406650ae 40 case OCC_TRIANGLE:
117Florian 9:d2a5406650ae 41 return new Triangle(interrupt_us);
117Florian 4:2febde858269 42 case OCC_WT:
117Florian 5:3a753cf68fac 43 default:
117Florian 7:a478d5cc411e 44 return new WT(interrupt_us);
117Florian 8:dd2da7c0c4c7 45
117Florian 4:2febde858269 46 }
117Florian 4:2febde858269 47 }
117Florian 4:2febde858269 48
117Florian 5:3a753cf68fac 49 void Occilator::setMasterVolume(long volume)
117Florian 5:3a753cf68fac 50 {
117Florian 5:3a753cf68fac 51 sMasterVolume=volume;
117Florian 5:3a753cf68fac 52 }
117Florian 5:3a753cf68fac 53
117Florian 3:32094530d55e 54 Occilator::Occilator(long interrupt_us)
117Florian 3:32094530d55e 55 {
117Florian 3:32094530d55e 56 myled1=1;
117Florian 3:32094530d55e 57 ::interrupt_us=interrupt_us;
117Florian 3:32094530d55e 58 if(part_num==0)
117Florian 3:32094530d55e 59 {
117Florian 3:32094530d55e 60 sTicker.attach_us(::tick,interrupt_us);
117Florian 3:32094530d55e 61 }
117Florian 3:32094530d55e 62 part_num++;
117Florian 3:32094530d55e 63 for(int i=0;i<OCCILATOR_PART_NUM;i++)
117Florian 3:32094530d55e 64 {
117Florian 3:32094530d55e 65 if(part[i]==NULL)
117Florian 3:32094530d55e 66 {
117Florian 3:32094530d55e 67 part[i]=this;
117Florian 3:32094530d55e 68 break;
117Florian 3:32094530d55e 69 }
117Florian 3:32094530d55e 70 }
117Florian 3:32094530d55e 71
117Florian 3:32094530d55e 72 m_Volume=0x10000;
117Florian 3:32094530d55e 73 }
117Florian 3:32094530d55e 74
117Florian 3:32094530d55e 75 Occilator::~Occilator()
117Florian 3:32094530d55e 76 {
117Florian 3:32094530d55e 77 part_num--;
117Florian 3:32094530d55e 78 for(int i=0;i<OCCILATOR_PART_NUM;i++)
117Florian 3:32094530d55e 79 {
117Florian 3:32094530d55e 80 if(part[i]==this)
117Florian 3:32094530d55e 81 {
117Florian 3:32094530d55e 82 part[i]=NULL;
117Florian 3:32094530d55e 83 break;
117Florian 3:32094530d55e 84 }
117Florian 3:32094530d55e 85 }
117Florian 3:32094530d55e 86 if(part_num<=0)
117Florian 3:32094530d55e 87 {
117Florian 3:32094530d55e 88 sTicker.detach();
117Florian 3:32094530d55e 89 }
117Florian 3:32094530d55e 90 }
117Florian 3:32094530d55e 91
117Florian 3:32094530d55e 92 void Occilator::setOmega(long speed)
117Florian 3:32094530d55e 93 {
117Florian 3:32094530d55e 94 m_Omega=speed;
117Florian 3:32094530d55e 95 myled2=1;
117Florian 3:32094530d55e 96 }
117Florian 3:32094530d55e 97
117Florian 3:32094530d55e 98 void Occilator::setVolume(int volume)
117Florian 3:32094530d55e 99 {
117Florian 3:32094530d55e 100 m_Volume=volume;
117Florian 3:32094530d55e 101 }
117Florian 3:32094530d55e 102
117Florian 3:32094530d55e 103 unsigned long Occilator::tick()
117Florian 3:32094530d55e 104 {
117Florian 3:32094530d55e 105 m_Angle+=m_Omega;
117Florian 5:3a753cf68fac 106 return 0L;
117Florian 3:32094530d55e 107 }
117Florian 3:32094530d55e 108
117Florian 3:32094530d55e 109 void ::tick()
117Florian 3:32094530d55e 110 {
117Florian 3:32094530d55e 111 long long value=0;
117Florian 3:32094530d55e 112
117Florian 3:32094530d55e 113 for (int i=0;i<OCCILATOR_PART_NUM;i++)
117Florian 3:32094530d55e 114 {
117Florian 3:32094530d55e 115 if (part[i]!=NULL)
117Florian 3:32094530d55e 116 {
117Florian 3:32094530d55e 117 value+=total_value_in_this_span + part[i]->tick();
117Florian 3:32094530d55e 118 }
117Florian 3:32094530d55e 119 }
117Florian 3:32094530d55e 120 value = value>=0x10000 ? 0xffff : value;
117Florian 5:3a753cf68fac 121 value = (sMasterVolume*value)>>16;
117Florian 3:32094530d55e 122 sAnalogOut.write_u16(value);
117Florian 3:32094530d55e 123 myled4=value > 0x80000000;
117Florian 3:32094530d55e 124 }