Beispiel #1
0
        public void Init()
        {
            chInfo = new ChInfo[maxCh];
            for (int i = 0; i < chInfo.Length; i++)
            {
                chInfo[i] = new ChInfo();

                // 内部変数
                // 高音域のみ通す(低音域をカットする)フィルタ設定(左右分)
                // カットする周波数の目安は20Hz~300Hz程度
                // 増幅量が大きくなれば、カットオフ周波数も大きくするとよい
                chInfo[i].hFreq = 1000f;
                chInfo[i].hQ    = (float)(1.0f / Math.Sqrt(2.0f));
                chInfo[i].lFreq = 300f;
                chInfo[i].lQ    = (float)(1.0f / Math.Sqrt(2.0f));

                chInfo[i].hsw       = false;
                chInfo[i].highpassL = new CMyFilter();
                chInfo[i].highpassR = new CMyFilter();

                chInfo[i].lsw      = false;
                chInfo[i].lowpassL = new CMyFilter();
                chInfo[i].lowpassR = new CMyFilter();

                updateParam(i);
            }
        }
Beispiel #2
0
 public void Init()
 {
     chInfo = new ChInfo[maxCh];
     for (int i = 0; i < chInfo.Length; i++)
     {
         chInfo[i] = new ChInfo((int)clock);
     }
 }
Beispiel #3
0
        public void SetReg(bool isSysIns, uint adr, byte data)
        {
            if (!isSysIns && adr == 0)
            {
                currentCh = Math.Max(Math.Min(data & 0x3f, 38), 0);
                if ((data & 0x80) != 0)
                {
                    Init();
                }
                return;
            }

            ChInfo info = sysInfo;

            if (!isSysIns)
            {
                info = chInfo[currentCh];
            }

            if (adr == 1)
            {
                info.sw     = ((data & 0x80) != 0);
                info.volume = (data & 0x7f) / (127.0f / 4.0f);
            }
            else if (adr == 2)
            {
                info.threshold = Math.Max(data / 255.0f, 0.1f);
            }
            else if (adr == 3)
            {
                info.ratio = Math.Max(data / (255.0f / 10.0f), 1.0f);
            }
            else if (adr == 4)
            {
                info.envFreq = data / (255.0f / 80.0f);
                info.envfilterL.LowPass(info.envFreq, info.envQ, samplerate);
                info.envfilterR.LowPass(info.envFreq, info.envQ, samplerate);
            }
            else if (adr == 5)
            {
                info.envQ = CMyFilter.QTable[data];
                info.envfilterL.LowPass(info.envFreq, info.envQ, samplerate);
                info.envfilterR.LowPass(info.envFreq, info.envQ, samplerate);
            }
            else if (adr == 6)
            {
                info.gainFreq = data / (255.0f / 80.0f);
                info.gainfilterL.LowPass(info.gainFreq, info.gainQ, samplerate);
                info.gainfilterR.LowPass(info.gainFreq, info.gainQ, samplerate);
            }
            else if (adr == 7)
            {
                info.gainQ = CMyFilter.QTable[data];
                info.gainfilterL.LowPass(info.gainFreq, info.gainQ, samplerate);
                info.gainfilterR.LowPass(info.gainFreq, info.gainQ, samplerate);
            }
        }
Beispiel #4
0
        public void Init()
        {
            chInfo = new ChInfo[maxCh];
            for (int i = 0; i < chInfo.Length; i++)
            {
                chInfo[i]    = new ChInfo();
                chInfo[i].sw = false;

                // 内部変数
                // 高音域のみ通す(低音域をカットする)フィルタ設定(左右分)
                // カットする周波数の目安は20Hz~300Hz程度
                // 増幅量が大きくなれば、カットオフ周波数も大きくするとよい
                chInfo[i].highpassL = new CMyFilter();
                chInfo[i].highpassL.HighPass(200.0f, (float)(1.0f / Math.Sqrt(2.0f)), clock);
                chInfo[i].highpassR = new CMyFilter();
                chInfo[i].highpassR.HighPass(200.0f, (float)(1.0f / Math.Sqrt(2.0f)), clock);
                chInfo[i].gain   = 300.0f;
                chInfo[i].volume = 0.1f;
            }
        }
Beispiel #5
0
        public void Init()
        {
            currentCh = 0;
            chInfo    = new ChInfo[maxCh];
            for (int i = 0; i < chInfo.Length; i++)
            {
                chInfo[i]    = new ChInfo();
                chInfo[i].sw = false;

                chInfo[i].threshold = 0.3f;
                chInfo[i].ratio     = 2.0f;
                chInfo[i].volume    = 2.0f;

                chInfo[i].envFreq     = 30.0f;
                chInfo[i].envQ        = 1.0f;
                chInfo[i].gainFreq    = 5.0f;
                chInfo[i].gainQ       = 1.0f;
                chInfo[i].envfilterL  = new CMyFilter();
                chInfo[i].envfilterR  = new CMyFilter(); // 音圧を検知するために使うローパスフィルタ
                chInfo[i].gainfilterL = new CMyFilter();
                chInfo[i].gainfilterR = new CMyFilter(); // 急激な音量変化を避けるためのローパスフィルタ
                SetLowPass(i, 30.0f, 1.0f, 5.0f, 1.0f);
            }

            sysInfo    = new ChInfo();
            sysInfo.sw = false;

            sysInfo.threshold = 0.3f;
            sysInfo.ratio     = 2.0f;
            sysInfo.volume    = 2.0f;

            sysInfo.envFreq     = 30.0f;
            sysInfo.envQ        = 1.0f;
            sysInfo.gainFreq    = 5.0f;
            sysInfo.gainQ       = 1.0f;
            sysInfo.envfilterL  = new CMyFilter();
            sysInfo.envfilterR  = new CMyFilter(); // 音圧を検知するために使うローパスフィルタ
            sysInfo.gainfilterL = new CMyFilter();
            sysInfo.gainfilterR = new CMyFilter(); // 急激な音量変化を避けるためのローパスフィルタ
            SetLowPass(-1, 30.0f, 1.0f, 5.0f, 1.0f);
        }
Beispiel #6
0
        public void Mix(int ch, ref int inL, ref int inR)
        {
            if (ch < 0)
            {
                return;
            }
            if (ch >= maxCh)
            {
                return;
            }
            if (chInfo == null)
            {
                return;
            }
            if (chInfo[ch] == null)
            {
                return;
            }
            if (!chInfo[ch].sw)
            {
                return;
            }

            ChInfo ci    = chInfo[ch];
            float  finL  = inL / 21474.83647f;
            float  finR  = inR / 21474.83647f;
            float  speed = (2.0f * 3.14159265f * ci.rate) / clock;            // 揺らぎのスピード。角速度ωと同じ。

            // inL[]、inR[]、outL[]、outR[]はそれぞれ入力信号と出力信号のバッファ(左右)
            // wavelenghtはバッファのサイズ、サンプリング周波数は44100Hzとする

            // 入力信号にコーラスかける
            // 角度θに角速度を加える
            ci.theta += speed;

            // 読み込み位置を揺らす量を計算
            // sin()関数の結果にdepthを掛ける
            float a = (float)(Math.Sin(ci.theta) * ci.depth);

            // 読み込み位置を揺らした際の前後の整数値を取得(あとで線形補間するため)
            int p1 = (int)a;
            int p2 = (int)(a + 1);

            // 前後の整数値から読み込み位置の値を線形補間で割り出す
            float lerpL1 = lerp(ci.ringbufL.Read(p1), ci.ringbufL.Read(p2), a - (float)p1);
            float lerpR1 = lerp(ci.ringbufR.Read(p1), ci.ringbufR.Read(p2), a - (float)p1);

            // 入力信号にディレイ信号を混ぜる
            float tmpL = (1.0f - ci.mix) * finL + ci.mix * lerpL1;
            float tmpR = (1.0f - ci.mix) * finR + ci.mix * lerpR1;

            // ディレイ信号として入力信号とフィードバック信号をリングバッファに書き込み
            ci.ringbufL.Write((1.0f - ci.feedback) * finL + ci.feedback * tmpL);
            ci.ringbufR.Write((1.0f - ci.feedback) * finR + ci.feedback * tmpR);


            // リングバッファの状態を更新する
            ci.ringbufL.Update();
            ci.ringbufR.Update();

            // 出力信号に書き込む
            finL = tmpL;
            finR = tmpR;

            inL = (int)(finL * 21474.83647f);
            inR = (int)(finR * 21474.83647f);
        }
Beispiel #7
0
        public void Mix(int ch, ref int inL, ref int inR, int wavelength = 1)
        {
            if (ch < 0)
            {
                return;
            }
            if (ch >= maxCh)
            {
                return;
            }
            if (chInfo == null)
            {
                return;
            }
            if (chInfo[ch] == null)
            {
                return;
            }
            if (!chInfo[ch].sw)
            {
                return;
            }
            ChInfo info = chInfo[ch];

            fbuf[0] = inL / 21474.83647f;
            fbuf[1] = inR / 21474.83647f;

            // inL[]、inR[]、outL[]、outR[]はそれぞれ入力信号と出力信号のバッファ(左右)
            // wavelenghtはバッファのサイズ、サンプリング周波数は44100Hzとする

            // 入力信号にエフェクトをかける
            // 入力信号の絶対値をとったものをローパスフィルタにかけて音圧を検知する
            float tmpL = info.envfilterL.Process(Math.Abs(fbuf[0]));
            float tmpR = info.envfilterR.Process(Math.Abs(fbuf[1]));

            // 音圧をもとに音量(ゲイン)を調整(左)
            float gainL = 1.0f;

            if (tmpL > info.threshold)
            {
                // スレッショルドを超えたので音量(ゲイン)を調節(圧縮)
                gainL = info.threshold + (tmpL - info.threshold) / info.ratio;
            }
            // 音量(ゲイン)が急激に変化しないようローパスフィルタを通す
            gainL = info.gainfilterL.Process(gainL);

            // 左と同様に右も音圧をもとに音量(ゲイン)を調整
            float gainR = 1.0f;

            if (tmpR > info.threshold)
            {
                gainR = info.threshold + (tmpR - info.threshold) / info.ratio;
            }
            gainR = info.gainfilterR.Process(gainR);


            // 入力信号に音量(ゲイン)をかけ、さらに最終的な音量を調整し出力する
            fbuf[0] = info.volume * gainL * fbuf[0];
            fbuf[1] = info.volume * gainR * fbuf[1];
            inL     = (int)(fbuf[0] * 21474.83647f);
            inR     = (int)(fbuf[1] * 21474.83647f);
        }