Florian's most newest Diary

ふろりあんの再最新日記

現在のソース

[global.h]

#define INTERRUPT_TIME_US 22

#include "Channel.h"

extern DigitalOut myled1;
extern DigitalOut myled2;
extern DigitalOut myled3;
extern DigitalOut myled4;

[main.cpp]

#include "mbed.h"
#define MAIN
#include "global.h"

#define ADD 0x2000000

static Channel* gChannel[2];

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);

int main() {
    gChannel[0]=new Channel(INTERRUPT_TIME_US);
    gChannel[0]->setOmega(ADD);
    gChannel[1]=new Channel(INTERRUPT_TIME_US);
    gChannel[1]->setOmega(ADD+0x100000);
    while(1) {
        wait(1);
    }
}

 [Channel.h]

#ifndef _CHANNEL_H_INCL
#define _CHANNEL_H_INCL

#define CHANNEL_PART_NUM 16

class Channel
{
    public:
    /**
    * Constructor(only)
    * to construct after mbed has started.
    * this constructor handles interval timer automatically.
    * @value interrupt_us interrupt span (micro second). it work at first time only.
    */
        Channel(long interrupt_us);

        /**
        * Destructor
        * this destructor anatach the interval timer automatically.
        */
        ~Channel();

        /**
        * Set angle speed(0x100000000 per 1 round)
        * frequency was depend on interrupt_us
        */
        void setOmega(long speed);

        /**
        * advance the Angle and caliculate value this span.
        * it was called by automatically from interval timer.
        * @return value on this tick(max 0xffff0000)
        */
        virtual unsigned long tick();

        long m_Angle;
        long m_Omega;
};
#endif

[Channel.cpp]

#include "mbed.h"
#include "global.h"
#include "Channel.h"

static long interrupt_us;
static int part_num=0;
static Channel* part[CHANNEL_PART_NUM];
static Ticker sTicker;
static long total_value_in_this_span;
static AnalogOut sAnalogOut(p18);

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

Channel::Channel(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<CHANNEL_PART_NUM;i++)
    {
        if(part[i]==NULL)
        {
            part[i]=this;
            break;
        }
    }
}

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

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

unsigned long Channel::tick()
{
    m_Angle+=m_Omega;
    if (m_Angle & 0x80000000)
    {
       myled3 = 1;
        return 0xffff0000;
    }
    else
    {
        myled3 = 0;
        return 0;
    }    
}

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

    for (int i=0;i<CHANNEL_PART_NUM;i++)
    {
        if (part[i]!=NULL)
        {
            value+=total_value_in_this_span + part[i]->tick();
        }
    }
    value = value>=0x100000000 ? 0xffff0000 : value;
    sAnalogOut=value;
    myled4=value > 0x80000000;
}

mbedって ソースを公開するってどうすればいいんだろう?githabにでも入れるのがいいのかなぁ? でも、ソースの在り処ってクラウドでしょ? この「パブリッシュ」ってメニューを使うのかなぁ?(使ったことがない)

超未完成な状態でPublishするとなんかマズそうなのでひとまずカット&ペースト。Apache Licence2です。超未完成なコードだけど参考にしたい人のために。

これに、

  • MIDIのノートナンバーを入れると12音平均律の角速度(周波数じゃなくて)を計算するヘルパ
  • ADSRエンベロープを出すジェネレータ
  • ディレイ付きLFOと一つのトラックでデチューンするジェネレータ
  • Channelクラスを派生して角度を元に4bit(16段階)の音色を作るWaveTableクラス(これを使ってノイズも作る)
  • MMLを解釈するクラス

辺りをつけるとシンセサイザーっぽくなるな。うわー、作るものたくさんだ。ネタは尽きないなぁ。チップチューンきちんとやろうとするとできることたくさんあるもんね。