// ソフトウェアMIDIシンセサイザ。
// Copyright(c)2003-2004 yuno
//追加 by Kobarin
#pragma warning(disable:4305)
#pragma warning(disable:4786)
namespace std
{
    typedef size_t size_t;
};
//ここまで
/*
    置換 by Kobarin
    std::max => __max
    std::min => __min
    std::memset => memset
    std::memcmp => memcmp
    channels[i].reset(new channel(factory, i == 9 ? 0x3C00 : 0x3C80));
    => channels[i]= std::auto_ptr<channel>(new channel(factory, i == 9 ? 0x3C00 : 0x3C80));

*/
#include "midisynth.hpp"

#include <cassert>
//namespace std{//追加 by Kobarin
#include <cmath>
//};            //追加 by Kobarin
#include <cstring>
#include <utility>

#ifdef __BORLANDC__
#include <fastmath.h>
namespace std{
    using ::_fm_sin;
    using ::_fm_cos;
    using ::_fm_log10;
}
#endif

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

//namespace midisynth{//削除 by Kobarin
    // チャンネルコンストラクタ。
    channel::channel(note_factory* factory_, int bank):
        factory(factory_), default_bank(bank)
    {
        //追加 by Kobarin
        //念のため各種変数を初期化
        /*program = 0;
        bank = 0;
        panpot = 0;
        volume = 0;
        expression = 0;
        pressure = 0;
        pitch_bend = 0;
        pitch_bend_sensitivity = 0;
        modulation_depth = 0;
        modulation_depth_range = 0;
        damper = 0;
        sostenute = 0;
        freeze = 0;
        fine_tuning = 0;
        coarse_tuning = 0;
        RPN = 0;
        NRPN = 0;
        mono = 0;
        mute = 0;
        tremolo_frequency = 0;
        vibrato_frequency = 0;
        frequency_multiplier = 0;
        master_frequency_multiplier = 0;
        system_mode = system_mode_default;
        //ここまで
        */
        notes.reserve(16);
        reset_all_parameters();
    }
    // チャンネルデストラクタ。
    channel::~channel()
    {
        all_sound_off_immediately();
    }
    // 発音中の音を合成する。
    int channel::synthesize(sample_t* out, std::size_t samples, double rate, int_least32_t master_volume, int master_balance)
    {
        double volume = mute ? 0.0 : std::pow(static_cast<double>(master_volume) * this->volume * expression / (16383.0 * 16383.0 * 16383.0), 2) * 16383.0;
        int num_notes = 0;
        std::vector<NOTE>::iterator i = notes.begin();
        while(i != notes.end()){
            class note* note = i->note;
            uint_least32_t panpot = note->get_panpot();
            if(this->panpot <= 8192){
                panpot = panpot * this->panpot / 8192;
            }else{
                panpot = panpot * (16384 - this->panpot) / 8192 + (this->panpot - 8192) * 2;
            }
            if(master_balance <= 8192){
                panpot = panpot * master_balance / 8192;
            }else{
                panpot = panpot * (16384 - master_balance) / 8192 + (master_balance - 8192) * 2;
            }
            sample_t left = static_cast<sample_t>(volume * std::cos(__max(0, panpot - 1) * (M_PI / 2 / 16382)));
            sample_t right = static_cast<sample_t>(volume * std::sin(__max(0, panpot - 1) * (M_PI / 2 / 16382)));
            bool ret = note->synthesize(out, samples, rate, left, right);
            if(ret){
                ++i;
            }else{
                i = notes.erase(i);
                delete note;
            }
            ++num_notes;
        }
        return num_notes;
    }
    // すべてのパラメータを初期状態に戻す。
    void channel::reset_all_parameters()
    {
        program = default_bank * 128;
        bank = default_bank;
        panpot = 8192;
        volume = 12800;
        fine_tuning = 8192;
        coarse_tuning = 8192;
        tremolo_frequency = 3;
        vibrato_frequency = 3;
        master_frequency_multiplier = 1;
        mono = false;
        mute = false;
        system_mode = system_mode_default;
        reset_all_controller();
    }
    // パラメータを初期状態に戻す。
    void channel::reset_all_controller()
    {
        expression = 16383;
        channel_pressure(0);
        pitch_bend = 8192;
        pitch_bend_sensitivity = 256;
        frequency_multiplier = 0;//追加 by Kobarin (初回の update_frequency_multiplier 呼び出し時に浮動小数点エラーが発生するのを回避） 
        update_frequency_multiplier();
        modulation_depth = 0;
        modulation_depth_range = 64;
        update_modulation();
        damper = -1;//added by Kobarin
        set_damper(0);
        set_sostenute(0);
        freeze = -1;//added by Kobarin
        set_freeze(0);
        RPN = 0x3FFF;
        NRPN = 0x3FFF;
    }
    // すべての音をノートオフする。
    void channel::all_note_off()
    {
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            if(i->status == NOTE::NOTEON){
                i->status = NOTE::NOTEOFF;
                i->note->note_off(64);
            }
        }
    }
    // すべての音をサウンドオフする。
    void channel::all_sound_off()
    {
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            if(i->status != NOTE::SOUNDOFF){
                i->status = NOTE::SOUNDOFF;
                i->note->sound_off();
            }
        }
    }
    // 即時消音。
    void channel::all_sound_off_immediately()
    {
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            delete i->note;
        }
        notes.clear();
    }
    // ノートオン。音を出す。
    void channel::note_on(int note, int velocity)
    {
        assert(note >= 0 && note < NUM_NOTES);
        assert(velocity >= 0 && velocity <= 127);

        note_off(note, 64);
        if(velocity){
            if(mono){
                all_sound_off();
            }
            class note* p = factory->note_on(program, note, velocity, frequency_multiplier);
            if(p){
                int assign = p->get_assign();
                if(assign){
                    for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
                        if(i->note->get_assign() == assign){
                            i->note->sound_off();
                        }
                    }
                }
                if(freeze){
                    p->set_freeze(freeze);
                }
                if(damper){
                    p->set_damper(damper);
                }
                if(modulation_depth){
                    double depth = static_cast<double>(modulation_depth) * modulation_depth_range / (16383.0 * 128.0);
                    p->set_vibrato(depth, vibrato_frequency);
                }
                if(pressure){
                    p->set_tremolo(pressure, tremolo_frequency);
                }
                notes.push_back(NOTE(p, note));
            }
        }
    }
    // ノートオフ。音がリリースタイムに入る。
    void channel::note_off(int note, int velocity)
    {
        assert(note >= 0 && note < NUM_NOTES);
        assert(velocity >= 0 && velocity <= 127);
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            if(i->key == note && i->status == NOTE::NOTEON){
                i->status = NOTE::NOTEOFF;
                i->note->note_off(velocity);
            }
        }
    }
    // ポリフォニックキープレッシャ。
    void channel::polyphonic_key_pressure(int note, int value)
    {
        assert(note >= 0 && note < NUM_NOTES);
        assert(value >= 0 && value <= 127);
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            if(i->key == note && i->status == NOTE::NOTEON){
                i->note->set_tremolo(value, tremolo_frequency);
            }
        }
    }
    // チャンネルプレッシャ。
    void channel::channel_pressure(int value)
    {
        assert(value >= 0 && value <= 127);
        if(pressure != value){
            pressure = value;
            for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
                if(i->status == NOTE::NOTEON){
                    i->note->set_tremolo(value, tremolo_frequency);
                }
            }
        }
    }
    // コントロールチェンジ。
    void channel::control_change(int control, int value)
    {
        assert(value >= 0 && value <= 0x7F);
        switch(control){
        case 0x00:
            bank_select((bank & 0x7F) | (value << 7));
            break;
        case 0x01:
            set_modulation_depth((modulation_depth & 0x7F) | (value << 7));
            break;
        case 0x06:
            set_registered_parameter((get_registered_parameter() & 0x7F) | (value << 7));
            break;
        case 0x07:
            volume = (volume & 0x7F) | (value << 7);
            break;
        case 0x0A:
            panpot = (panpot & 0x7F) | (value << 7);
            break;
        case 0x0B:
            expression = (expression & 0x7F) | (value << 7);
            break;
        case 0x20:
            bank_select((bank & 0x7F) | (value << 7));
            break;
        case 0x21:
            set_modulation_depth((modulation_depth & ~0x7F) | value);
            break;
        case 0x26:
            set_registered_parameter((get_registered_parameter() & ~0x7F) | value);
            break;
        case 0x27:
            volume = (volume & ~0x7F) | value;
            break;
        case 0x2A:
            panpot = (panpot & ~0x7F) | value;
            break;
        case 0x2B:
            expression = (expression & ~0x7F) | value;
            break;
        case 0x40:
            set_damper(value);
            break;
        case 0x42:
            set_sostenute(value);
            break;
        case 0x45:
            set_freeze(value);
            break;
        case 0x60:
            set_registered_parameter(__max(0x3FFF, get_registered_parameter() + 1));
            break;
        case 0x61:
            set_registered_parameter(__min(0, get_registered_parameter() - 1));
            break;
        case 0x62:
            set_NRPN((NRPN & ~0x7F) | value);
            break;
        case 0x63:
            set_NRPN((NRPN & 0x7F) | (value << 7));
            break;
        case 0x64:
            set_RPN((RPN & ~0x7F) | value);
            break;
        case 0x65:
            set_RPN((RPN & 0x7F) | (value << 7));
            break;
        case 0x78:
            all_sound_off();
            break;
        case 0x79:
            reset_all_controller();
            break;
        case 0x7B:
        case 0x7C:
        case 0x7D:
            all_note_off();
            break;
        case 0x7E:
            mono_mode_on();
            break;
        case 0x7F:
            poly_mode_on();
            break;
        }
    }
    // バンクセレクト
    void channel::bank_select(int value)
    {
        switch(system_mode){
        case system_mode_gm:
            break;
        case system_mode_gs:
            if(((bank & 0x3F80) == 0x3C00) == ((value & 0x3F80) == 0x3C00)){
                set_bank(value);
            }
            break;
        case system_mode_xg:
            if(default_bank == 0x3C00){
                set_bank(0x3C00 | (value & 0x7F));
            }else if((value & 0x3F80) == 0x3F80){
                set_bank(0x3C00 | (value & 0x7F));
            }else{
                set_bank(value);
            }
            break;
        default:
            if(default_bank == 0x3C00){
                set_bank(0x3C00 | (value & 0x7F));
            }else{
                set_bank(value);
            }
            break;
        }
    }
    // ダンパー効果。
    void channel::set_damper(int value)
    {
        if(damper != value){
            damper = value;
            for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
                i->note->set_damper(value);
            }
        }
    }
    // ソステヌート効果。
    void channel::set_sostenute(int value)
    {
        sostenute = value;
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            i->note->set_sostenute(value);
        }
    }
    // フリーズ効果。
    void channel::set_freeze(int value)
    {
        if(freeze != value){
            freeze = value;
            for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
                i->note->set_freeze(value);
            }
        }
    }
    // RPN取得。
    int channel::get_registered_parameter()
    {
        switch(RPN){
        case 0x0000:
            return pitch_bend_sensitivity;
        case 0x0001:
            return fine_tuning;
        case 0x0002:
            return coarse_tuning;
        case 0x0005:
            return modulation_depth_range;
        default:
            return 0;
        }
    }
    // RPN設定。
    void channel::set_registered_parameter(int value)
    {
        switch(RPN){
        case 0x0000:
            set_pitch_bend_sensitivity(value);
            break;
        case 0x0001:
            set_fine_tuning(value);
            break;
        case 0x0002:
            set_coarse_tuning(value);
            break;
        case 0x0005:
            set_modulation_depth_range(value);
            break;
        default:
            break;
        }
    }
    // 周波数倍率を再計算し更新する。
    void channel::update_frequency_multiplier()
    {
        double value = master_frequency_multiplier
                    * std::pow(2.0, (coarse_tuning - 8192) / (128.0 * 100.0 * 12.0)
                                + (fine_tuning - 8192) / (8192.0 * 100.0 * 12.0)
                                + static_cast<double>(pitch_bend - 8192) * pitch_bend_sensitivity / (8192.0 * 128.0 * 12.0));
        if(frequency_multiplier != value){
            frequency_multiplier = value;
            for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
                i->note->set_frequency_multiplier(value);
            }
        }
    }
    // モジュレーションデプス効果の更新。
    void channel::update_modulation()
    {
        double depth = static_cast<double>(modulation_depth) * modulation_depth_range / (16383.0 * 128.0);
        for(std::vector<NOTE>::iterator i = notes.begin(); i != notes.end(); ++i){
            i->note->set_vibrato(depth, vibrato_frequency);
        }
    }

    // シンセサイザコンストラクタ。
    synthesizer::synthesizer(note_factory* factory)
    {
        for(int i = 0; i < 16; ++i){
            //channels[i].reset(new channel(factory, i == 9 ? 0x3C00 : 0x3C80));//削除 by Kobarin
            channels[i]= std::auto_ptr<channel>(new channel(factory, i == 9 ? 0x3C00 : 0x3C80));//追加 by Kobarin
        }
        reset_all_parameters();
    }
    // チャンネル取得。
    channel* synthesizer::get_channel(int ch)
    {
        assert(ch >= 0 && ch < NUM_CHANNELS);
        return channels[ch].get();
    }
    // 音を合成する。発音数を返す。
    int synthesizer::synthesize(sample_t* output, std::size_t samples, double rate)
    {
        std::size_t n = samples * 2;
        std::vector<sample_t> buf(n);
        int num_notes = synthesize_mixing(&buf[0], samples, rate);
        if(num_notes){
            for(std::size_t i = 0; i < n; ++i){
                /*int_least32_t x = buf[i];
                if(x < -32767){
                    output[i] = -32767;
                }else if(x > 32767){
                    output[i] = 32767;
                }else{
                    output[i] = static_cast<int_least16_t>(x);
                }*/
                output[i] = buf[i];
            }
        }else{
            memset(output, 0, sizeof(int_least16_t) * n);
        }
        return num_notes;
    }
    int synthesizer::synthesize_mixing(sample_t* output, std::size_t samples, double rate)
    {
        if(active_sensing == 0){
            all_sound_off();
            active_sensing = -1;
        }else if(active_sensing > 0){
            active_sensing = __max(0, active_sensing - samples / rate);
        }
        int_least32_t volume = static_cast<int_least32_t>(main_volume) * master_volume / 16384;
        int num_notes = 0;
        for(int i = 0; i < NUM_CHANNELS; ++i){
            num_notes += channels[i]->synthesize(output, samples, rate, volume, master_balance);
        }
        return num_notes;
    }
    // シンセサイザを完全にリセットする。
    void synthesizer::reset()
    {
        all_sound_off_immediately();
        reset_all_parameters();
    }
    // すべてのパラメータを初期状態に戻す。
    void synthesizer::reset_all_parameters()
    {
        active_sensing = -1;
        main_volume = 8192;
        master_volume = 16383;
        master_balance = 8192;
        master_fine_tuning = 8192;
        master_coarse_tuning = 8192;
        master_frequency_multiplier = 1;
        system_mode = system_mode_default;
        for(int i = 0; i < NUM_CHANNELS; ++i){
            channels[i]->reset_all_parameters();
        }
    }
    // パラメータを初期状態に戻す。
    void synthesizer::reset_all_controller()
    {
        for(int i = 0; i < NUM_CHANNELS; ++i){
            channels[i]->reset_all_controller();
        }
    }
    // オールノートオフ。すべての音をノートオフする。
    void synthesizer::all_note_off()
    {
        for(int i = 0; i < NUM_CHANNELS; ++i){
            channels[i]->all_note_off();
        }
    }
    // オールサウンドオフ。すべての音をサウンドオフする。
    void synthesizer::all_sound_off()
    {
        for(int i = 0; i < NUM_CHANNELS; ++i){
            channels[i]->all_sound_off();
        }
    }
    // 即時消音。
    void synthesizer::all_sound_off_immediately()
    {
        for(int i = 0; i < NUM_CHANNELS; ++i){
            channels[i]->all_sound_off_immediately();
        }
    }
    // システムエクスクルーシブメッセージの解釈実行。
    void synthesizer::sysex_message(const void* pvdata, std::size_t size)
    {
        const unsigned char* data = reinterpret_cast<const unsigned char*>(pvdata);
        if(size == 6 && memcmp(data, "\xF0\x7E\x7F\x09\x01\xF7", 6) == 0){
            /* GM system on */
            set_system_mode(system_mode_gm);
        }else if(size == 6 && memcmp(data, "\xF0\x7E\x7F\x09\x02\xF7", 6) == 0){
            /* GM system off */
            set_system_mode(system_mode_gm2);
        }else if(size == 6 && memcmp(data, "\xF0\x7E\x7F\x09\x03\xF7", 6) == 0){
            /* GM2 system on */
            set_system_mode(system_mode_gm2);
        }else if(size == 11 && memcmp(data, "\xF0\x41", 2) == 0 && memcmp(data + 3, "\x42\x12\x40\x00\x7F\x00\x41\xF7", 8) == 0){
            /* GS reset */
            set_system_mode(system_mode_gs);
        }else if(size == 9 && memcmp(data, "\xF0\x43", 2) == 0 && (data[2] & 0xF0) == 0x10 && memcmp(data + 3, "\x4C\x00\x00\x7E\x00\xF7", 6) == 0){
            /* XG system on */
            set_system_mode(system_mode_xg);
        }else if(size == 8 && memcmp(data, "\xF0\x7F\x7F\x04\x01", 5) == 0 && data[7] == 0xF7){
            /* master volume */
            set_master_volume(/*(data[5] & 0x7F) |*/ ((data[6] & 0x7F) << 7));
        //}else if (size == 11 && memcmp(data, "\xF0\x41\x10\x42\x12\x40\x00\x04", 8) == 0 && data[10] == 0xF7) {
        }else if (size == 11 && memcmp(data, "\xF0\x41", 2) == 0 && (data[2] & 0xF0) == 0x10 &&
                  memcmp(data + 3, "\x42\x12\x40\x00\x04", 5) == 0 && data[10] == 0xF7) {
            /* master volume(GS) */
            int vol = (data[8] & 0x7f) << 7;
            set_master_volume(vol);
        //}else if (size == 9 && memcmp(data, "\xF0\x43\x10\x4c\x00\x00\x04", 7) == 0 && data[8] == 0xF7) {
        }else if (size == 9 && memcmp(data, "\xF0\x43", 2) == 0 &&(data[2] & 0xF0) == 0x10 &&
                        memcmp(data + 3, "\x4c\x00\x00\x04", 4) == 0 && data[8] == 0xF7) {
            /* master volume(XG) */
            int vol = (data[7] & 0x7f) << 7;
            set_master_volume(vol);
        }else if(size == 8 && memcmp(data, "\xF0\x7F\x7F\x04\x02", 5) == 0 && data[7] == 0xF7){
            /* master balance */
            set_master_balance((data[5] & 0x7F) | ((data[6] & 0x7F) << 7));
        }else if(size == 8 && memcmp(data, "\xF0\x7F\x7F\x04\x03", 5) == 0 && data[7] == 0xF7){
            /* master fine tuning */
            set_master_fine_tuning((data[5] & 0x7F) | ((data[6] & 0x7F) << 7));
        }else if(size == 8 && memcmp(data, "\xF0\x7F\x7F\x04\x04", 5) == 0 && data[7] == 0xF7){
            /* master coarse tuning */
            set_master_coarse_tuning((data[5] & 0x7F) | ((data[6] & 0x7F) << 7));
        }else if(size == 11 && memcmp(data, "\xF0\x41", 2) == 0 && (data[2] & 0xF0) == 0x10 && memcmp(data + 3, "\x42\x12\x40", 3) == 0 && (data[6] & 0xF0) == 0x10 && data[7] == 0x15 && data[10] == 0xF7){
            /* use for rhythm part */
            int channel = data[6] & 0x0F;
            int map = data[8];
            if(map == 0){
                channels[channel]->set_bank(0x3C80);
            }else{
                channels[channel]->set_bank(0x3C00);
            }
            channels[channel]->program_change(0);
        }
    }
    // MIDIイベントの解釈実行。
    void synthesizer::midi_event(int event, int param1, int param2)
    {
        switch(event & 0xF0){
        case 0x80:
            note_off(event & 0x0F, param1 & 0x7F, param2 & 0x7F);
            break;
        case 0x90:
            note_on(event & 0x0F, param1 & 0x7F, param2 & 0x7F);
            break;
        case 0xA0:
            polyphonic_key_pressure(event & 0x0F, param1 & 0x7F, param2 & 0x7F);
            break;
        case 0xB0:
            control_change(event & 0x0F, param1 & 0x7F, param2 & 0x7F);
            break;
        case 0xC0:
            program_change(event & 0x0F, param1 & 0x7F);
            break;
        case 0xD0:
            channel_pressure(event & 0x0F, param1 & 0x7F);
            break;
        case 0xE0:
            pitch_bend_change(event & 0x0F, ((param2 & 0x7F) << 7) | (param1 & 0x7F));
            break;
        case 0xFE:
            active_sensing = 0.33f;
            break;
        case 0xFF:
            all_sound_off();
            reset_all_parameters();
            break;
        default:
            break;
        }
    }
    // システムモードを変更する。
    void synthesizer::set_system_mode(system_mode_t mode)
    {
        all_sound_off();
        reset_all_parameters();
        system_mode = mode;
        for(int i = 0; i < NUM_CHANNELS; ++i){
            channels[i]->set_system_mode(mode);
        }
    }
    // マスターチューニングを再計算し更新する。
    void synthesizer::update_master_frequency_multiplier()
    {
        double value = std::pow(2.0, (master_coarse_tuning - 8192) / (128.0 * 100.0 * 12.0)
                                + (master_fine_tuning - 8192) / (8192.0 * 100.0 * 12.0));
        if(master_frequency_multiplier != value){
            master_frequency_multiplier = value;
            for(int i = 0; i < NUM_CHANNELS; ++i){
                channels[i]->set_master_frequency_multiplier(value);
            }
        }
    }

    // 正弦テーブル。正弦波ジェネレータ用。
    namespace{
        class sine_table{
        public:
            enum{ DIVISION = 4096 };
            sine_table();
            int_least16_t get(int n)const{ return data[n]; }
        private:
            int_least16_t data[DIVISION];
        }sine_table;

        sine_table::sine_table()
        {
            for(int i = 0; i < DIVISION; ++i){
                data[i] = static_cast<int_least16_t>(32767 * std::sin(i * 2 * M_PI / DIVISION));
            }
        }
    }
    // 正弦波生成器コンストラクタ。
    inline sine_wave_generator::sine_wave_generator():
        position(0), step(0)
    {
    }
    inline sine_wave_generator::sine_wave_generator(double cycle):
        position(0)
    {
        set_cycle(cycle);
    }
    // 正弦波の周期を変更する。
    void sine_wave_generator::set_cycle(double cycle)
    {
        if(cycle){
            step = static_cast<uint_least32_t>(sine_table::DIVISION * 32768.0 / cycle);
        }else{
            step = 0;
        }
    }
    // モジュレーションを加える。
    void sine_wave_generator::add_modulation(int_least32_t x)
    {
        position += static_cast<int_least32_t>(static_cast<int_least64_t>(step) * x >> 16);
    }
    // 次のサンプルを取り出す。
    inline int sine_wave_generator::get_next()
    {
        return sine_table.get((position += step) / 32768 % sine_table::DIVISION);
    }
    // 次のサンプルを取り出す(周波数変調付き)。
    inline int sine_wave_generator::get_next(int_least32_t modulation)
    {
        uint_least32_t m = modulation * sine_table::DIVISION / 65536;
        uint_least32_t p = ((position += step) / 32768 + m) % sine_table::DIVISION;
        return sine_table.get(p);
    }

    // 対数変換テーブル。エンベロープジェネレータのディケイ以降で使う。
    namespace{
        #define LOG10_32767 4.5154366811416989472479934140484
        #define LOGTABLE_SIZE 4096
        #define LOGTABLE_FACTOR (LOGTABLE_SIZE / LOG10_32767)
        class log_table{
        public:
            log_table();
            uint_least16_t get(int x)const{ return data[x]; }
        private:
            uint_least16_t data[LOGTABLE_SIZE];
        }log_table;
        log_table::log_table()
        {
            for(int i = 0; i < LOGTABLE_SIZE; ++i){
                data[i] = std::pow(10.0, static_cast<double>(i) / LOGTABLE_FACTOR);
            }
        }
    }

    // レートテーブル。AR、DR、SR、RRの計算処理の高速化。
    namespace{
        struct envelope_table{
            envelope_table();
            uint_least32_t TL[128];
            uint_least32_t SL[16][128];
            double AR[64][128];
            double RR[64][128];
        }const envelope_table;

        envelope_table::envelope_table()
        {
            for(int t = 0; t < 128; ++t){
                double fTL = 32767 * std::pow(10.0, t * -0.75 / 10);
                TL[t] = fTL;
                if(TL[t] == 0){
                    TL[t] = 1;
                }
                for(int s = 0; s < 16; ++s){
                    double x = fTL * std::pow(10.0, s * -3.0 / 10);
                    if(x <= 1){
                        SL[s][t] = 0;
                    }else{
                        SL[s][t] = 65536 * LOGTABLE_FACTOR * std::log10(x);
                    }
                }
            }
            for(int x = 0; x < 64; ++x){
                double attack_time = 15.3262 * std::pow(10.0, x * -0.75 / 10);
                double release_time = 211.84 * std::pow(10.0, x * -0.75 / 10);
                for(int t = 0; t < 128; ++t){
                    AR[x][t] = TL[t] / attack_time;
                    RR[x][t] = 65536 * LOGTABLE_FACTOR * 48.0 / 10 * TL[t] / 32767 / release_time;
                }
            }
        }
    }

    // エンベロープ生成器コンストラクタ。
    envelope_generator::envelope_generator(int AR_, int DR_, int SR_, int RR_, int SL, int TL_):
        AR(AR_), DR(DR_), SR(SR_), RR(RR_), TL(TL_),
        state(ATTACK), current(0), rate(1), hold(0), freeze(0)
    {
        if(AR >= 63) AR = 63;
        if(DR >= 63) DR = 63;
        if(SR >= 63) SR = 63;
        if(RR >= 63) RR = 63;
        assert(AR >= 0);
        assert(DR >= 0);
        assert(SR >= 0);
        assert(RR >= 0);
        assert(SL >= 0 && SL <= 15);
        assert(TL >= 0 && TL <= 127);

        fTL = envelope_table.TL[TL];
        fSS = fSL = envelope_table.SL[SL][TL];
        fAR = 0;
        fDR = 0;
        fSR = 0;
        fRR = 0;
        fOR = 0;
        fDRR = 0;
        fDSS = 0;
    }
    // 再生レートを設定する。
    inline void envelope_generator::set_rate(double rate)
    {
        this->rate = rate ? rate : 1;
        update_parameters();
    }
    // ホールド(ダンパー&ソステヌート)を設定する。
    void envelope_generator::set_hold(double hold)
    {
        if(this->hold > hold || state <= SASTAIN || current >= fSL){
            this->hold = hold;
            update_parameters();
        }
    }
    // フリーズを設定する。
    void envelope_generator::set_freeze(double freeze)
    {
        if(this->freeze > freeze || state <= SASTAIN || current >= fSL){
            this->freeze = freeze;
            update_parameters();
        }
    }
    // 各パラメータの更新。
    void envelope_generator::update_parameters()
    {
        double fAR = envelope_table.AR[AR][TL] / rate;
        double fDR = envelope_table.RR[DR][TL] / rate;
        double fSR = envelope_table.RR[SR][TL] / rate;
        double fRR = envelope_table.RR[RR][TL] / rate;

        if(fRR < 1){
            fRR = 1;
        }
        if(hold > 0){
            fRR = fSR * hold + fRR * (1 - hold);
        }
        if(freeze > 0){
            fDR *= (1 - freeze);
            fSR *= (1 - freeze);
            fRR *= (1 - freeze);
        }
        if(fAR < 1){
            fAR = 1;
        }
        this->fAR = static_cast<uint_least32_t>(fAR);
        this->fDR = static_cast<uint_least32_t>(fDR);
        this->fSR = static_cast<uint_least32_t>(fSR);
        this->fRR = static_cast<uint_least32_t>(fRR);
        this->fOR = static_cast<uint_least32_t>(envelope_table.RR[63][0] / rate);
        this->fSS = __max(this->fDR, fSL);
        this->fDRR = __max(this->fDR, this->fRR);
        this->fDSS = __max(this->fDRR, this->fSS);
    }
    // キーオフ。リリースに入る。
    void envelope_generator::key_off()
    {
        switch(state){
        case ATTACK:
            state = ATTACK_RELEASE;
            break;
        case DECAY:
            state = DECAY_RELEASE;
            break;
        case SASTAIN:
            state = RELEASE;
            break;
        default:
            break;
        }
    }
    // サウンドオフ。急速消音モードに入る。
    void envelope_generator::sound_off()
    {
        switch(state){
        case ATTACK:
        case ATTACK_RELEASE:
            if(current){
                current = 65536 * LOGTABLE_FACTOR * std::log10(static_cast<double>(current));
            }
            break;
        default:
            break;
        }
        state = SOUNDOFF;
    }
    // リリースからサウンドオフに移るレベル。リリースの長い音をいつまでも発音
    // してるとCPUパワーの無駄なので適当なところで切るため。減衰は対数なので
    // 音量が真にゼロになるには無限の時間を要する。実際には整数に切り捨てて
    // 処理しているので１未満になったら無音になるとはいえ…。
    // 不自然でない程度になるべく高い値の方がパフォーマンスが向上する。
    #define SOUNDOFF_LEVEL 1024
    // 次のサンプルを得る。
    int envelope_generator::get_next()
    {
        uint_least32_t current = this->current;
        switch(state){
        case ATTACK:
            if(current < fTL){
                return this->current = current + fAR;
            }
            this->current = 65536 * LOGTABLE_FACTOR * std::log10(static_cast<double>(fTL));
            state = DECAY;
            return fTL;
        case DECAY:
            if(current > fSS){
                this->current = current -= fDR;
                return log_table.get(current / 65536);
            }
            this->current = current = fSL;
            state = SASTAIN;
            return log_table.get(current / 65536);
        case SASTAIN:
            if(current > fSR){
                this->current = current -= fSR;
                int n = log_table.get(current / 65536);
                if(n > 1){
                    return n;
                }
            }
            state = FINISHED;
            return 0;
        case ATTACK_RELEASE:
            if(current < fTL){
                return this->current = current + fAR;
            }
            this->current = 65536 * LOGTABLE_FACTOR * std::log10(static_cast<double>(fTL));
            state = DECAY_RELEASE;
            return fTL;
        case DECAY_RELEASE:
            if(current > fDSS){
                this->current = current -= fDRR;
                return log_table.get(current / 65536);
            }
            this->current = current = fSL;
            state = RELEASE;
            return log_table.get(current / 65536);
        case RELEASE:
            if(current > fRR){
                this->current = current -= fRR;
                int n = log_table.get(current / 65536);
                if(n > SOUNDOFF_LEVEL){
                    return n;
                }
                state = SOUNDOFF;
                return n;
            }
            state = FINISHED;
            return 0;
        case SOUNDOFF:
            if(current > fOR){
                this->current = current -= fOR;
                int n = log_table.get(current / 65536);
                if(n > 1){
                    return n;
                }
            }
            state = FINISHED;
            return 0;
        default:
            return 0;
        }
    }

    namespace{
        // キースケーリングテーブル
        const int keyscale_table[4][128] = {
            {
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
                 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
            }, {
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
                 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
                 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
                 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
            }, {
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
                 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
                 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8,
                 8, 8, 8, 8, 8, 9, 9, 9,10,10,10,10,10,10,10,10,
                10,11,11,11,12,12,12,12,12,12,12,12,12,13,13,13,
                14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,
                15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
            }, {
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 5,
                 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9,10,10,11,
                12,12,12,12,12,12,12,13,13,14,14,15,16,16,16,16,
                16,16,16,17,17,18,18,19,20,20,20,20,20,20,20,21,
                21,22,22,23,24,24,24,24,24,24,24,25,25,26,26,27,
                28,28,28,28,28,28,28,29,29,30,30,31,31,31,31,31,
                31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
            }
        };
        // ディチューンテーブル
        const double detune_table[4][128] = {
            { 0 },
            {
                0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
                0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
                0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
                0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,
                0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,
                0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,
                0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,
                0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,
                0.106, 0.106, 0.106, 0.159, 0.159, 0.159, 0.159, 0.159,
                0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212,
                0.212, 0.212, 0.212, 0.264, 0.264, 0.264, 0.264, 0.264,
                0.264, 0.264, 0.264, 0.317, 0.317, 0.317, 0.317, 0.370,
                0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,
                0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,
                0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,
                0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423
            }, {
                0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
                0.000, 0.000, 0.000, 0.000, 0.000, 0.053, 0.053, 0.053,
                0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,
                0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,
                0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,
                0.106, 0.106, 0.106, 0.106 ,0.106, 0.159, 0.159, 0.159,
                0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212 ,0.212,
                0.212, 0.212, 0.212, 0.264, 0.264, 0.264, 0.264, 0.264,
                0.264, 0.264, 0.264, 0.317, 0.317, 0.317, 0.317, 0.370,
                0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,
                0.423, 0.476, 0.476, 0.529, 0.582, 0.582, 0.582, 0.582,
                0.582, 0.582 ,0.582, 0.635, 0.635, 0.688, 0.688, 0.741,
                0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846 ,0.846,
                0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846,
                0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846
            }, {
                0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
                0.000, 0.000, 0.000, 0.000, 0.000, 0.106, 0.106, 0.106,
                0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,
                0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.159,
                0.159, 0.159, 0.159, 0.159, 0.212, 0.212, 0.212, 0.212,
                0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.264,
                0.264, 0.264, 0.264, 0.264, 0.264, 0.264, 0.264, 0.317,
                0.317, 0.317, 0.317, 0.370, 0.423, 0.423, 0.423, 0.423,
                0.423, 0.423, 0.423, 0.423, 0.423, 0.476, 0.476, 0.529,
                0.582, 0.582, 0.582, 0.582, 0.582, 0.582, 0.582, 0.635,
                0.635, 0.688, 0.688, 0.741, 0.846, 0.846, 0.846, 0.846,
                0.846, 0.846, 0.846, 0.899, 0.899, 1.005, 1.005, 1.058,
                1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164,
                1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164,
                1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164,
                1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164
            }
        };
        // LFOテーブル
        const uint_least32_t ams_table[4] = {
            0,
            128 - 128 * std::pow(10.0, -1.44 / 10),
            128 - 128 * std::pow(10.0, -5.9 / 10),
            128 - 128 * std::pow(10.0, -11.8 / 10)
        };
    }

    // FMオペレータのコンストラクタ。
    fm_operator::fm_operator(int AR, int DR, int SR, int RR, int SL, int TL, int KS, int ML_, int DT_, int AMS_, int key):
        eg(AR * 2 + keyscale_table[KS][key],
           DR * 2 + keyscale_table[KS][key],
           SR * 2 + keyscale_table[KS][key],
           RR * 4 + keyscale_table[KS][key] + 2,
           SL,
           TL)
    {
        assert(AR >= 0 && AR <= 31);
        assert(DR >= 0 && DR <= 31);
        assert(SR >= 0 && SR <= 31);
        assert(RR >= 0 && RR <= 15);
        assert(SL >= 0);
        assert(TL >= 0);
        assert(KS >= 0 && KS <= 3);
        assert(ML_ >= 0 && ML_ <= 15);
        assert(DT_ >= 0 && DT_ <= 7);
        assert(AMS_ >= 0 && AMS_ <= 3);
        assert(key >= 0 && key <= 127);

        if(DT_ >= 4){
            DT = -detune_table[DT_ - 4][key];
        }else{
            DT = detune_table[DT_][key];
        }
        if(ML_ == 0){
            ML = 0.5;
        }else{
            ML = ML_;
        }

        ams_factor = ams_table[AMS_] / 2;
        ams_bias = 32768 - ams_factor * 256;
    }
    // 再生周波数設定。
    void fm_operator::set_freq_rate(double freq, double rate)
    {
        freq += DT;
        freq *= ML;
        swg.set_cycle(rate / freq);
        eg.set_rate(rate);
    }
    // 次のサンプルを得る。
    inline int fm_operator::get_next()
    {
        return static_cast<int_least32_t>(swg.get_next()) * eg.get_next() >> 15;
    }
    inline int fm_operator::get_next(int modulate)
    {
        return static_cast<int_least32_t>(swg.get_next(modulate)) * eg.get_next() >> 15;
    }
    inline int fm_operator::get_next(int ams, int modulate)
    {
        return (static_cast<int_least32_t>(swg.get_next(modulate)) * eg.get_next() >> 15) * (ams * ams_factor + ams_bias) >> 15;
    }

    // ビブラートテーブル。
    namespace{
        class vibrato_table{
        public:
            enum{ DIVISION = 16384 };
            vibrato_table();
            int_least32_t get(int x)const{ return data[x + DIVISION / 2]; }
        private:
            int_least32_t data[DIVISION];
        }vibrato_table;

        vibrato_table::vibrato_table()
        {
            for(int i = 0; i < DIVISION; ++i){
                double x = (static_cast<double>(i) / DIVISION - 0.5) * 256.0 / 12.0;
                data[i] = static_cast<int_least32_t>((std::pow(2.0, x) - 1) * 65536.0);
            }
        }
    }
    
    // FM音源コンストラクタ。
    fm_sound_generator::fm_sound_generator(const FMPARAMETER& params, int note, double frequency_multiplier):
        op1(params.op1.AR, params.op1.DR, params.op1.SR, params.op1.RR, params.op1.SL, params.op1.TL, params.op1.KS, params.op1.ML, params.op1.DT, params.op1.AMS, note),
        op2(params.op2.AR, params.op2.DR, params.op2.SR, params.op2.RR, params.op2.SL, params.op2.TL, params.op2.KS, params.op2.ML, params.op2.DT, params.op2.AMS, note),
        op3(params.op3.AR, params.op3.DR, params.op3.SR, params.op3.RR, params.op3.SL, params.op3.TL, params.op3.KS, params.op3.ML, params.op3.DT, params.op3.AMS, note),
        op4(params.op4.AR, params.op4.DR, params.op4.SR, params.op4.RR, params.op4.SL, params.op4.TL, params.op4.KS, params.op4.ML, params.op4.DT, params.op4.AMS, note),
        ALG(params.ALG),
        freq(440 * std::pow(2.0, (note - 69) / 12.0)),
        freq_mul(frequency_multiplier),
        tremolo_depth(0),
        tremolo_freq(1),
        vibrato_depth(0),
        vibrato_freq(1),
        rate(0),
        feedback(0),
        damper(0),
        sostenute(0)
    {
        assert(ALG >= 0 && ALG <= 7);
        assert(params.LFO >= 0 && params.LFO <= 7);
        assert(params.FB >= 0 && params.FB <= 7);

        static const int feedbacks[8] = {
            31, 6, 5, 4, 3, 2, 1, 0
        };
        FB = feedbacks[params.FB];

        static const double ams_table[8] = {
            3.98, 5.56, 6.02, 6.37, 6.88, 9.63, 48.1, 72.2
        };
        ams_freq = ams_table[params.LFO];
        ams_enable = (params.op1.AMS + params.op2.AMS + params.op3.AMS + params.op4.AMS != 0);
    }
    // 再生レート設定。
    void fm_sound_generator::set_rate(double rate)
    {
        if(this->rate != rate){
            this->rate = rate;
            ams_lfo.set_cycle(rate / ams_freq);
            vibrato_lfo.set_cycle(rate / vibrato_freq);
            tremolo_lfo.set_cycle(rate / tremolo_freq);
            double f = freq * freq_mul;
            op1.set_freq_rate(f, rate);
            op2.set_freq_rate(f, rate);
            op3.set_freq_rate(f, rate);
            op4.set_freq_rate(f, rate);
        }
    }
    // 周波数倍率設定。
    void fm_sound_generator::set_frequency_multiplier(double value)
    {
        freq_mul = value;
        double f = freq * freq_mul;
        op1.set_freq_rate(f, rate);
        op2.set_freq_rate(f, rate);
        op3.set_freq_rate(f, rate);
        op4.set_freq_rate(f, rate);
    }
    // ダンパー効果設定。
    void fm_sound_generator::set_damper(int damper)
    {
        this->damper = damper;
        double value = 1.0 - (1.0 - damper / 127.0) * (1.0 - sostenute / 127.0);
        op1.set_hold(value);
        op2.set_hold(value);
        op3.set_hold(value);
        op4.set_hold(value);
    }
    // ソステヌート効果設定。
    void fm_sound_generator::set_sostenute(int sostenute)
    {
        this->sostenute = sostenute;
        double value = 1.0 - (1.0 - damper / 127.0) * (1.0 - sostenute / 127.0);
        op1.set_hold(value);
        op2.set_hold(value);
        op3.set_hold(value);
        op4.set_hold(value);
    }
    // フリーズ効果設定。
    void fm_sound_generator::set_freeze(int freeze)
    {
        double value = freeze / 127.0;
        op1.set_freeze(value);
        op2.set_freeze(value);
        op3.set_freeze(value);
        op4.set_freeze(value);
    }
    // トレモロ効果設定。
    void fm_sound_generator::set_tremolo(int depth, double frequency)
    {
        tremolo_depth = depth;
        tremolo_freq = frequency;
        tremolo_lfo.set_cycle(rate / frequency);
    }
    // ビブラート効果設定。
    void fm_sound_generator::set_vibrato(double depth, double frequency)
    {
        vibrato_depth = depth * (vibrato_table::DIVISION / 256.0);
        vibrato_freq = frequency;
        vibrato_lfo.set_cycle(rate / frequency);
    }
    // キーオフ。
    void fm_sound_generator::key_off()
    {
        op1.key_off();
        op2.key_off();
        op3.key_off();
        op4.key_off();
    }
    // サウンドオフ。
    void fm_sound_generator::sound_off()
    {
        op1.sound_off();
        op2.sound_off();
        op3.sound_off();
        op4.sound_off();
    }
    // 音の発生が終了したかどうかを返す。
    bool fm_sound_generator::is_finished()const
    {
        switch(ALG){
        case 0:
        case 1:
        case 2:
        case 3:
            return op4.is_finished();
        case 4:
            return op2.is_finished() && op4.is_finished();
        case 5:
        case 6:
            return op2.is_finished() && op3.is_finished() && op4.is_finished();
        case 7:
            return op1.is_finished() && op2.is_finished() && op3.is_finished() && op4.is_finished();
        default:
            assert(!"fm_sound_generator: invalid algorithm number");
            return true;
        }
    }
    // 次のサンプルを得る。
    int fm_sound_generator::get_next()
    {
        if(vibrato_depth){
            int x = static_cast<int_least32_t>(vibrato_lfo.get_next()) * vibrato_depth >> 15;
            int_least32_t modulation = vibrato_table.get(x);
            op1.add_modulation(modulation);
            op2.add_modulation(modulation);
            op3.add_modulation(modulation);
            op4.add_modulation(modulation);
        }
        int feedback = (this->feedback << 1) >> FB;
        int ret;
        if(ams_enable){
            int ams = ams_lfo.get_next() >> 7;
            switch(ALG){
            case 0:
                ret = op4(ams, op3(ams, op2(ams, this->feedback = op1(ams, feedback))));
                break;
            case 1:
                ret = op4(ams, op3(ams, op2(ams, 0) + (this->feedback = op1(ams, feedback))));
                break;
            case 2:
                ret = op4(ams, op3(ams, op2(ams, 0)) + (this->feedback = op1(ams, feedback)));
                break;
            case 3:
                ret = op4(ams, op3(ams, 0) + op2(ams, this->feedback = op1(ams, feedback)));
                break;
            case 4:
                ret = op4(ams, op3(ams, 0)) + op2(ams, this->feedback = op1(ams, feedback));
                break;
            case 5:
                this->feedback = feedback = op1(ams, feedback);
                ret = op4(ams, feedback) + op3(ams, feedback) + op2(ams, feedback);
                break;
            case 6:
                ret = op4(ams, 0) + op3(ams, 0) + op2(ams, this->feedback = op1(ams, feedback));
                break;
            case 7:
                ret = op4(ams, 0) + op3(ams, 0) + op2(ams, 0) + (this->feedback = op1(ams, feedback));
                break;
            default:
                assert(!"fm_sound_generator: invalid algorithm number");
                return 0;
            }
        }else{
            switch(ALG){
            case 0:
                ret = op4(op3(op2(this->feedback = op1(feedback))));
                break;
            case 1:
                ret = op4(op3(op2() + (this->feedback = op1(feedback))));
                break;
            case 2:
                ret = op4(op3(op2()) + (this->feedback = op1(feedback)));
                break;
            case 3:
                ret = op4(op3() + op2(this->feedback = op1(feedback)));
                break;
            case 4:
                ret = op4(op3()) + op2(this->feedback = op1(feedback));
                break;
            case 5:
                this->feedback = feedback = op1(feedback);
                ret = op4(feedback) + op3(feedback) + op2(feedback);
                break;
            case 6:
                ret = op4() + op3() + op2(this->feedback = op1(feedback));
                break;
            case 7:
                ret = op4() + op3() + op2() + (this->feedback = op1(feedback));
                break;
            default:
                assert(!"fm_sound_generator: invalid algorithm number");
                return 0;
            }
        }
        if(tremolo_depth){
            int_least32_t x = 4096 - (((static_cast<int_least32_t>(tremolo_lfo.get_next()) + 32768) * tremolo_depth) >> 11);
            ret = ret * x >> 12;
        }
        return ret;
    }

    // FMノートのコンストラクタ。
    fm_note::fm_note(const FMPARAMETER& params, int note, int velocity_, int panpot, int assign, double frequency_multiplier):
        note(assign, panpot),
        fm(params, note, frequency_multiplier),
        velocity(velocity_)
    {
        assert(velocity >= 1 && velocity <= 127);
        ++velocity;
    }
    // 波形出力。
    bool fm_note::synthesize(sample_t* buf, std::size_t samples, double rate, sample_t left, sample_t right)
    {
        //left = (left * velocity) >> 7;
        //right = (right * velocity) >> 7;
        left = (left * velocity) / 128.0;//>> 7;  //修正 by Kobarin
        right = (right * velocity) / 128.0;//>> 7;//
        
        fm.set_rate(rate);
        for(std::size_t i = 0; i < samples; ++i){
            int_least32_t sample = fm.get_next();
            //buf[i * 2 + 0] += (sample * left) >> 14;
            //buf[i * 2 + 1] += (sample * right) >> 14;
            buf[i * 2 + 0] += (sample * left) / (16384.0 * 32768.0); //修正 by Kobarin(64bit float 用に調整するため、32768.0 で割る)
            buf[i * 2 + 1] += (sample * right) / (16384.0 * 32768.0);//
        }
        return !fm.is_finished();
    }
    // ノートオフ。
    void fm_note::note_off(int)
    {
        fm.key_off();
    }
    // サウンドオフ。
    void fm_note::sound_off()
    {
        fm.sound_off();
    }
    // 周波数倍率設定。
    void fm_note::set_frequency_multiplier(double value)
    {
        fm.set_frequency_multiplier(value);
    }
    // トレモロ効果設定。
    void fm_note::set_tremolo(int depth, double freq)
    {
        fm.set_tremolo(depth, freq);
    }
    // ビブラート効果設定。
    void fm_note::set_vibrato(double depth, double freq)
    {
        fm.set_vibrato(depth, freq);
    }
    // ダンパー効果設定。
    void fm_note::set_damper(int value)
    {
        fm.set_damper(value);
    }
    // ソステヌート効果設定。
    void fm_note::set_sostenute(int value)
    {
        fm.set_sostenute(value);
    }
    // フリーズ効果設定。
    void fm_note::set_freeze(int value)
    {
        fm.set_freeze(value);
    }

    // FMノートファクトリ初期化。
    fm_note_factory::fm_note_factory()
    {
        clear();
    }
    // クリア。
    void fm_note_factory::clear()
    {
        // デフォルトの音色(sin波)
        static const struct FMPARAMETER param = {
            7, 0, 0,    // ALG FB LFO
            //AR DR SR RR SL  TL KS ML DT AMS
            { 31, 0, 0,15, 0,  0, 0, 0, 0, 0 },
            {  0, 0, 0,15, 0,127, 0, 0, 0, 0 },
            {  0, 0, 0,15, 0,127, 0, 0, 0, 0 },
            {  0, 0, 0,15, 0,127, 0, 0, 0, 0 }
        };
        drums.clear();
        programs.clear();
        programs[-1] = param;
    }
    // 音色パラメータの正当性検査
    namespace{
        bool is_valid_fmparameter(const FMPARAMETER& p)
        {
            return p.ALG >= 0 && p.ALG <= 7
                && p.FB >= 0 && p.FB <= 7
                && p.LFO >= 0 && p.LFO <= 7
                && p.op1.AR >= 0 && p.op1.AR <= 31
                && p.op1.DR >= 0 && p.op1.DR <= 31
                && p.op1.SR >= 0 && p.op1.SR <= 31
                && p.op1.RR >= 0 && p.op1.RR <= 15
                && p.op1.SL >= 0 && p.op1.SL <= 15
                && p.op1.TL >= 0 && p.op1.TL <= 127
                && p.op1.KS >= 0 && p.op1.KS <= 3
                && p.op1.ML >= 0 && p.op1.ML <= 15
                && p.op1.DT >= 0 && p.op1.DT <= 7
                && p.op1.AMS >= 0 && p.op1.AMS <= 3
                && p.op2.AR >= 0 && p.op2.AR <= 31
                && p.op2.DR >= 0 && p.op2.DR <= 31
                && p.op2.SR >= 0 && p.op2.SR <= 31
                && p.op2.RR >= 0 && p.op2.RR <= 15
                && p.op2.SL >= 0 && p.op2.SL <= 15
                && p.op2.TL >= 0 && p.op2.TL <= 127
                && p.op2.KS >= 0 && p.op2.KS <= 3
                && p.op2.ML >= 0 && p.op2.ML <= 15
                && p.op2.DT >= 0 && p.op2.DT <= 7
                && p.op2.AMS >= 0 && p.op2.AMS <= 3
                && p.op3.AR >= 0 && p.op3.AR <= 31
                && p.op3.DR >= 0 && p.op3.DR <= 31
                && p.op3.SR >= 0 && p.op3.SR <= 31
                && p.op3.RR >= 0 && p.op3.RR <= 15
                && p.op3.SL >= 0 && p.op3.SL <= 15
                && p.op3.TL >= 0 && p.op3.TL <= 127
                && p.op3.KS >= 0 && p.op3.KS <= 3
                && p.op3.ML >= 0 && p.op3.ML <= 15
                && p.op3.DT >= 0 && p.op3.DT <= 7
                && p.op3.AMS >= 0 && p.op3.AMS <= 3
                && p.op4.AR >= 0 && p.op4.AR <= 31
                && p.op4.DR >= 0 && p.op4.DR <= 31
                && p.op4.SR >= 0 && p.op4.SR <= 31
                && p.op4.RR >= 0 && p.op4.RR <= 15
                && p.op4.SL >= 0 && p.op4.SL <= 15
                && p.op4.TL >= 0 && p.op4.TL <= 127
                && p.op4.KS >= 0 && p.op4.KS <= 3
                && p.op4.ML >= 0 && p.op4.ML <= 15
                && p.op4.DT >= 0 && p.op4.DT <= 7
                && p.op4.AMS >= 0 && p.op4.AMS <= 3;
        }
        bool is_valid_drumparameter(const DRUMPARAMETER& p)
        {
            return is_valid_fmparameter(p)
                && p.key >= 0 && p.key <= 127
                && p.panpot >= 0 && p.panpot <= 16383;
        }
    }
    // 音色パラメータ取得。
    void fm_note_factory::get_program(int program, FMPARAMETER& p)
    {
        if(programs.find(program) != programs.end()){
            p = programs[program];
        }else if(programs.find(program & 0x3FFF) != programs.end()){
            p = programs[program & 0x3FFF];
        }else if(programs.find(program & 0x7F) != programs.end()){
            p = programs[program & 0x7F];
        }else{
            p = programs[-1];
        }
    }
    // 音色パラメータをセット。
    bool fm_note_factory::set_program(int number, const FMPARAMETER& p)
    {
        if(is_valid_fmparameter(p)){
            programs[number] = p;
            return true;
        }else{
            return false;
        }
    }
    // ドラム音色パラメータをセット。
    bool fm_note_factory::set_drum_program(int number, const DRUMPARAMETER& p)
    {
        if(is_valid_drumparameter(p)){
            drums[number] = p;
            return true;
        }else{
            return false;
        }
    }
    // ノートオン。
    note* fm_note_factory::note_on(int_least32_t program, int note, int velocity, double frequency_multiplier)
    {
        bool drum = (program >> 14) == 120;
        if(drum){
            int n = (program & 0x3FFF) * 128 + note;
            struct DRUMPARAMETER* p;
            if(drums.find(n) != drums.end()){
                p = &drums[n];
            }else if(drums.find(n & 0x3FFF) != drums.end()){
                p = &drums[n & 0x3FFF];
            }else if(drums.find(note) != drums.end()){
                p = &drums[note];
            }else if(drums.find(-1) != drums.end()){
                p = &drums[-1];
            }else{
                return NULL;
            }
            return new fm_note(*p, p->key, velocity, p->panpot, p->assign, 1);
        }else{
            struct FMPARAMETER* p;
            if(programs.find(program) != programs.end()){
                p = &programs[program];
            }else if(programs.find(program & 0x7F) != programs.end()){
                p = &programs[program & 0x7F];
            }else{
                p = &programs[-1];
            }
            return new fm_note(*p, note, velocity, 8192, 0, frequency_multiplier);
        }
    }
//}//削除 by Kobarin
