Beispiel #1
0
        public void UpdatePSG(PSGWrapper psg, int chn)
        {
            if (note == VirtualKeyboard.Note.None || note == VirtualKeyboard.Note.NoteOff)
            {
                psg.SetAttenuation(chn, 0);
                return;
            }

            if (!samplePlayback)
            {
                psg.SetAttenuation(chn, GetCurrentVol( ));
            }

            if (!m_UpdatedFrequency || (updatesFrequency && !samplePlayback))
            {
                if (chn < 3)
                {
                    if (!samplePlayback)
                    {
                        psg.SetNote(chn, GetNoteOffset(( int )note), octave, GetFreqOffset());
                    }
                    else
                    {
                        psg.SetFrequency(chn, 1);
                    }
                }
                else if (!samplePlayback)
                {
                    int chn2, fb;
                    chn2 = (noiseMode [m_NoiseCounter] & 0x2);
                    fb   = (noiseMode [m_NoiseCounter] & 0x1);

                    if (chn2 == 0)
                    {
                        int cmd = 0xE0 | ((fb > 0 ? 4 : 0)) | ((GetNoteOffset(( int )note) - 1) % 3);
                        //Debug.Log ( System.Convert.ToString ( cmd, 2 ) );
                        psg.PSGDirectWrite(cmd);
                    }
                    else
                    {
                        psg.PSGDirectWrite(fb > 0 ? 0xE7 : 0xE3);
                        psg.SetNote(2, GetNoteOffset(( int )note), octave, GetFreqOffset());
                    }
                }
            }

            ClockInstrument();
            m_UpdatedFrequency = true;
        }
Beispiel #2
0
        public void UpdatePSGSample(PSGWrapper psg, int chn)
        {
            if (!samplePlayback)
            {
                return;
            }

            if (GetCurrentVol() == 0)
            {
                return;
            }

            if (chn == 3)
            {
                psg.PSGDirectWrite(noiseFlip ? 0xE2 : 0xE1);
                noiseFlip = !noiseFlip;
            }

            if (note == VirtualKeyboard.Note.None || note == VirtualKeyboard.Note.NoteOff)
            {
                psg.SetAttenuation(chn, 0);
                return;
            }

            if (m_SampleTimer <= 0)
            {
                m_SampleFreq  = (PSGWrapper.CalculateNoteFreq(GetNoteOffset(( int )note), octave) + GetFreqOffset( ));
                m_SampleTimer = SAMPLE_RATE / m_SampleFreq;
            }

            float divider = SAMPLE_RATE / m_SampleFreq;
            float phase   = (m_SampleTimer % divider) / divider;
            float attn    = 0;
            int   smp     = 0;

            switch (customWaveform)
            {
            case Wave.Pulse:
                attn = phase < ((float)m_PWM / (float)PWM_STEPS) ? 0 : LINEAR_STEPS;
                smp  = ( int )attn;
                break;

            case Wave.Saw:
                attn = Mathf.Ceil(phase * LINEAR_STEPS);
                smp  = ( int )attn;
                break;

            case Wave.Triangle:
                attn = phase * LINEAR_STEPS * 2;
                attn = Mathf.Ceil(Mathf.Abs(attn - LINEAR_STEPS));
                smp  = ( int )attn;
                break;

            case Wave.Sample:
                if (waveTable != null)
                {
                    float noteOffset = (PSGWrapper.CalculateNoteFreq(GetNoteOffset((int)note), octave) + GetFreqOffset( )) / PSGWrapper.CalculateNoteFreq(sampleRelNote + 1, 0);
                    divider = SAMPLE_RATE / (waveTableSampleRate * noteOffset);
                    float pos         = divider - m_SampleTimer;
                    int   sampleIndex = ( int )((m_SampleTimer / divider) % waveTable.Length);
                    if (loopSample || (m_SampleTimer / divider) < waveTable.Length)
                    {
                        smp = waveTable [sampleIndex];
                    }
                    else
                    {
                        smp = LINEAR_STEPS;
                    }
                }
                break;

            case Wave.Sine:
                attn = (1f + Mathf.Sin(2 * Mathf.PI * m_SampleFreq * m_SampleTimer / SAMPLE_RATE)) * 0.5f * LINEAR_STEPS;
                smp  = ( int )attn;
                break;
            }

            if (customWaveform == Wave.Sample)
            {
                m_SampleTimer++;
            }
            else
            {
                m_SampleTimer--;
            }

            if (m_LastSample != LINEAR_VOLUME_TABLE [smp])
            {
                attn = Math.Max(0, LINEAR_VOLUME_TABLE [smp] - (0xF - GetCurrentVol( )));
                psg.SetAttenuation(chn, ( int )attn);
            }
            m_LastSample = LINEAR_VOLUME_TABLE [smp];
        }
Beispiel #3
0
    public void OnIrqCallback()
    {
        if (!m_IsPlaying)
        {
            return;
        }

        m_Counter++;

        if (m_Counter >= playbackSpeed)
        {
            if (m_IsStopping)
            {
                m_IsPlaying  = false;
                m_IsStopping = true;
                return;
            }

            m_Counter = 0;
            int patternBreakTarget = -1;

            for (int i = 0; i < data.channels; i++)
            {
                m_PlayingPattern = m_CurrentPattern;
                SongData.ColumnEntry col = data.GetPatternColumn(m_CurrentPattern, i);

                if (col == null)
                {
                    //m_Instruments [ i ].note = VirtualKeyboard.Note.NoteOff;
                    //psg.SetAttenuation ( i, 0 );
                    continue;
                }
                if (mute[i])
                {
                    m_Instruments[i].note = VirtualKeyboard.Note.NoteOff;
                }
                else
                {
                    int volume = col.data[m_CurrentLine, 2];
                    if (volume >= 0)
                    {
                        m_Instruments[i].relativeVolume = volume;
                    }

                    if (col.data[m_CurrentLine, 0] > 0)
                    {
                        VirtualKeyboard.Note note = VirtualKeyboard.GetNote(col.data[m_CurrentLine, 0]);
                        if (note == VirtualKeyboard.Note.NoteOff)
                        {
                            m_Instruments[i].note = VirtualKeyboard.Note.NoteOff;
                            psg.SetAttenuation(i, 0);
                        }
                        else if (col.data[m_CurrentLine, 1] < instruments.presets.Length)
                        {
                            m_PrevInstruments[i]            = m_Instruments[i];
                            m_Instruments[i]                = instruments.presets[col.data[m_CurrentLine, 1]];
                            m_Instruments[i].relativeVolume = volume >= 0 ? volume : 0xF;
                            m_Instruments[i].note           = note;
                            m_Instruments[i].noteOffset     = data.transposeTable[m_CurrentPattern][i];
                            m_Instruments[i].octave         = VirtualKeyboard.GetOctave(col.data[m_CurrentLine, 0]);
                        }
                    }
                }


                int fxVal = col.data [m_CurrentLine, 4];

                if (fxVal >= 0)
                {
                    switch (col.data [m_CurrentLine, 3])
                    {
                    //arpreggio
                    case 0x00:
                        if (fxVal == 0)
                        {
                            m_Instruments [i].arpeggio = new int [0];
                        }
                        else
                        {
                            int hiArp, loArp;
                            SplitByte(fxVal, out hiArp, out loArp);
                            m_Instruments [i].arpeggio = new int [3] {
                                0, loArp, hiArp
                            };
                            m_Instruments[i].arpLoopPoint = 3;
                        }
                        break;

                    case 0x01:
                        m_Instruments [i].portamentoSpeed = fxVal;
                        break;

                    case 0x02:
                        m_Instruments [i].portamentoSpeed = -fxVal;
                        break;

                    case 0x03:
                        if (m_Instruments [i].samplePlayback)
                        {
                            m_Instruments [i].pulseWidth = m_PrevInstruments [i].pulseWidth;
                        }
                        m_Instruments [i].SetAutoPortamento(m_PrevInstruments[i], fxVal);
                        break;

                    case 0x04:
                        int speed, depth;
                        SplitByte(fxVal, out depth, out speed);
                        m_Instruments [i].vibratoDepth = depth;
                        m_Instruments [i].vibratoSpeed = speed;
                        break;

                    case 0x08:
                        int left, right;
                        SplitByte(fxVal, out right, out left);
                        psg.SetStereo(i, left != 0, right != 0);
                        break;

                    case 0x0B:
                        //loop point
                        break;

                    case 0x0D:
                        if (m_CurrentPattern >= data.numPatterns - 1)
                        {
                            break;
                        }

                        if (fxVal < data.patternLength)
                        {
                            m_PatternBreakTarget = fxVal;
                        }
                        else
                        {
                            m_PatternBreakTarget = 0;
                        }

                        patternBreakTarget = m_PatternBreakTarget;
                        break;

                    case 0x0F:
                        playbackSpeed = fxVal;
                        break;

                    case 0x10:
                        m_Instruments [i].noteDelay = fxVal;
                        break;

                    case 0x20:
                        int mode, fb;
                        SplitByte(fxVal, out mode, out fb);

                        int val = (mode << 1) | fb;
                        m_Instruments[i].noiseMode = new int[] { val };
                        break;

                    case 0x40:
                        m_Instruments [i].pulseWidthPanSpeed = fxVal;
                        break;

                    case 0xFF:
                        psg.PSGDirectWrite(fxVal);
                        break;
                    }
                }
            }

            m_MoveLine++;
            if (patternBreakTarget >= 0)
            {
                m_CurrentLine = patternBreakTarget;
                m_CurrentPattern++;
            }
            else
            {
                m_CurrentLine++;
                if (m_CurrentLine >= data.patternLength)
                {
                    m_CurrentLine = 0;
                    m_CurrentPattern++;

                    if (m_CurrentPattern >= data.numPatterns)
                    {
                        m_CurrentPattern = m_PatternLoop;
                        if (m_Loops >= 0)
                        {
                            m_IsStopping = m_Loops == 0;
                            m_Loops--;
                        }
                    }
                }
            }
        }

        for (int i = 0; i < data.channels; i++)
        {
            if (m_Instruments [i].noteDelay > 0)
            {
                m_Instruments [i].noteDelay--;
                m_PrevInstruments [i].UpdatePSG(psg, i);
                m_ChnAttenuation[i] = m_PrevInstruments[i].GetCurrentVol();
            }
            else
            {
                m_Instruments [i].UpdatePSG(psg, i);
                m_ChnAttenuation[i] = m_Instruments[i].GetCurrentVol();
            }

            if (mute[i])
            {
                m_ChnAttenuation[i] = 0;
            }
        }
    }