daglem / reSID

MOS 6581 / 8580 SID software emulator
49 stars 1 forks source link

cycles_per_sample wrong? #2

Open rtlprmft opened 7 months ago

rtlprmft commented 7 months ago

Hi Dag, maybe, you remember me. I once ported VICE to OS/2 ;) Currently working on my own emulator as a fun project using reSID and I found something that bothers me.

If I am not mistaken, for a PAL C64 with 985248 cpu clock ticks per second and a sampling rate of 48kHz, I should get 957 samples per frame (with a frame size of 19656 cpu clock ticks). With the algorithm implemented in sid.cc, I only get 913 samples. Here is an example which demonstrates that. (cnt1 is the algorithm from reSID, cnt2 is a naive floating point implementation for comparison). Am I misunderstanding something here? (The code also contains a suggestion for a fix)

Thanks for reSID!

void test()
{
    int cycles_per_sample2  = 985248./48000*0x10000+0.5;

    // Original implementation
    int cycles_per_sample = (985248./48000)*0x10000 + 0.5;

    // My fixed implementation
    //int_t cycles_per_sample = (985248./48000-1)*0x10000 + 0.5;

    int_t sample_offset = 0;

    size_t cnt1 = 0;
    size_t cnt2 = 0;

    double T = 0;

    for (int i=0; i<19656; i++)
    {
        uint32_t delta_t = 1;

        T += float(cycles_per_sample)/0x1000;
        if (int32_t(i*0x10000/cycles_per_sample2)!=cnt2)
            cnt2++;

        int32_t next_sample_offset = sample_offset + cycles_per_sample;
        int32_t delta_t_sample = next_sample_offset >> 16;

        if (delta_t_sample > delta_t)
            delta_t_sample = delta_t;

        if ((delta_t -= delta_t_sample) == 0)
        {
            sample_offset -= delta_t_sample << 16;
            continue;
        }

        sample_offset = next_sample_offset & 0xffff;
        cnt1++;
    }

    cout << cnt1 << endl;
    cout << cnt2 << endl;
}
rtlprmft commented 7 months ago

I just realized that with this fix, the output frequency is wrong by 5%. I fixed that for my case (resample_fast and delta_t==1) by commenting /for (int i = 0; i < delta_t_sample; i++)/ in clock_resample_fastmem, as it turns out that I now miss the step when delte_t_sample==0. This results in correct frequencies, but according to my FFT, the filter cut-off frequency is now wrong. I fixed that in set_sampling_parameters by

  double f_cycles_per_sample = clock_freq/sample_freq+1;
  double f_samples_per_cycle = 1./f_cycles_per_sample;

Now for me everything looks consistent, but I might miss some deeper problems that arise by my previous change. Any expert help is welcome.