Skip to content

Commit 41d587d

Browse files
committed
eminline: add muldiv64 and muldivu64 functions
sound: correct subtle timing issues, add -sound support, add resampling at the edge
1 parent f3e4db2 commit 41d587d

File tree

6 files changed

+551
-109
lines changed

6 files changed

+551
-109
lines changed

src/emu/resampler.cpp

Lines changed: 183 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,10 @@ void audio_resampler_hq::apply(const emu::detail::output_buffer_flat<sample_t> &
260260
}
261261
}
262262

263-
void audio_resampler_hq::apply(const emu::detail::output_buffer_interleaved<s16> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const
263+
void audio_resampler_hq::apply(const emu::detail::output_buffer_interleaved<s16> &src, sound_stream &dest, u32 srcc, u32 destc, float gain) const
264264
{
265+
u64 dest_sample = dest.start_index();
266+
u32 samples = dest.samples();
265267
u32 seconds = dest_sample / m_ft;
266268
u32 dsamp = dest_sample % m_ft;
267269
u32 ssamp = (u64(dsamp) * m_fs) / m_ft;
@@ -271,7 +273,7 @@ void audio_resampler_hq::apply(const emu::detail::output_buffer_interleaved<s16>
271273
gain /= 32768;
272274

273275
const s16 *s = src.ptrs(srcc, ssample - src.sync_sample());
274-
sample_t *d = dest.data();
276+
u32 dest_index = 0;
275277
int step = src.channels();
276278
for(u32 sample = 0; sample != samples; sample++) {
277279
sample_t acc = 0;
@@ -281,7 +283,7 @@ void audio_resampler_hq::apply(const emu::detail::output_buffer_interleaved<s16>
281283
acc += *filter++ * *s1;
282284
s1 -= step;
283285
}
284-
*d++ += acc * gain;
286+
dest.add(destc, dest_index++, acc * gain);
285287
phase += m_delta;
286288
s += m_skip * step;
287289
while(phase >= m_fsm) {
@@ -292,7 +294,36 @@ void audio_resampler_hq::apply(const emu::detail::output_buffer_interleaved<s16>
292294
}
293295

294296

295-
void audio_resampler_hq::apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const
297+
void audio_resampler_hq::apply_copy(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const
298+
{
299+
u32 seconds = dest_sample / m_ft;
300+
u32 dsamp = dest_sample % m_ft;
301+
u32 ssamp = (u64(dsamp) * m_fs) / m_ft;
302+
u64 ssample = ssamp + u64(m_fs) * seconds;
303+
u32 phase = (dsamp * m_ftm) % m_fsm;
304+
305+
gain *= 32768;
306+
307+
const sample_t *s = src.ptrs(srcc, ssample - src.sync_sample());
308+
s16 *d = dest.data() + destc;
309+
for(u32 sample = 0; sample != samples; sample++) {
310+
sample_t acc = 0;
311+
const sample_t *s1 = s;
312+
const float *filter = m_coefficients[phase >> m_phase_shift].data();
313+
for(u32 k = 0; k != m_order_per_lane; k++)
314+
acc += *filter++ * *s1--;
315+
*d = acc * gain;
316+
d += dchannels;
317+
phase += m_delta;
318+
s += m_skip;
319+
while(phase >= m_fsm) {
320+
phase -= m_fsm;
321+
s ++;
322+
}
323+
}
324+
}
325+
326+
void audio_resampler_hq::apply_add(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const
296327
{
297328
u32 seconds = dest_sample / m_ft;
298329
u32 dsamp = dest_sample % m_ft;
@@ -433,10 +464,156 @@ void audio_resampler_lofi::apply(const emu::detail::output_buffer_flat<sample_t>
433464
}
434465
}
435466

436-
void audio_resampler_lofi::apply(const emu::detail::output_buffer_interleaved<s16> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const
467+
void audio_resampler_lofi::apply(const emu::detail::output_buffer_interleaved<s16> &src, sound_stream &dest, u32 srcc, u32 destc, float gain) const
437468
{
469+
u64 dest_sample = dest.start_index();
470+
u32 samples = dest.samples();
471+
u32 seconds = dest_sample / m_ft;
472+
u32 dsamp = dest_sample % m_ft;
473+
u64 ssamp = (u64(dsamp) * m_fs * 0x1000) / m_ft;
474+
u64 ssample = (ssamp >> 12) + u64(m_fs) * seconds;
475+
u32 phase = ssamp & 0xfff;
476+
if(m_source_divide > 1) {
477+
u32 delta = ssample % m_source_divide;
478+
phase = (phase | (delta << 12)) / m_source_divide;
479+
ssample -= delta;
480+
}
481+
482+
gain /= 32768;
483+
484+
// We're getting 2 samples latency, which is small enough
485+
486+
ssample -= 4*m_source_divide;
487+
488+
const s16 *s = src.ptrs(srcc, ssample - src.sync_sample());
489+
490+
std::function<s16()> reader;
491+
if(m_source_divide == 1)
492+
reader = [s, schannels = src.channels()]() mutable -> sample_t { s16 r = *s; s += schannels; return r; };
493+
else
494+
reader = [s, schannels = src.channels(), count = m_source_divide]() mutable -> sample_t { s32 sm = 0; for(u32 i=0; i != count; i++) { sm += *s; s += schannels; } return sm / count; };
495+
496+
phase <<= 12;
497+
498+
sample_t s0 = reader();
499+
sample_t s1 = reader();
500+
sample_t s2 = reader();
501+
sample_t s3 = reader();
502+
503+
int dest_index = 0;
504+
for(u32 sample = 0; sample != samples; sample++) {
505+
u32 cphase = phase >> 12;
506+
dest.add(destc, dest_index++, gain * (- s0 * interpolation_table[0][0x1000-cphase] + s1 * interpolation_table[1][0x1000-cphase] + s2 * interpolation_table[1][cphase] - s3 * interpolation_table[0][cphase]));
507+
508+
phase += m_step;
509+
if(phase & 0x1000000) {
510+
phase &= 0xffffff;
511+
s0 = s1;
512+
s1 = s2;
513+
s2 = s3;
514+
s3 = reader();
515+
}
516+
}
438517
}
439518

440-
void audio_resampler_lofi::apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const
519+
void audio_resampler_lofi::apply_copy(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const
441520
{
521+
u32 seconds = dest_sample / m_ft;
522+
u32 dsamp = dest_sample % m_ft;
523+
u64 ssamp = (u64(dsamp) * m_fs * 0x1000) / m_ft;
524+
u64 ssample = (ssamp >> 12) + u64(m_fs) * seconds;
525+
u32 phase = ssamp & 0xfff;
526+
if(m_source_divide > 1) {
527+
u32 delta = ssample % m_source_divide;
528+
phase = (phase | (delta << 12)) / m_source_divide;
529+
ssample -= delta;
530+
}
531+
532+
gain *= 32768;
533+
534+
// We're getting 2 samples latency, which is small enough
535+
536+
ssample -= 4*m_source_divide;
537+
538+
const sample_t *s = src.ptrs(srcc, ssample - src.sync_sample());
539+
540+
std::function<sample_t()> reader;
541+
if(m_source_divide == 1)
542+
reader = [s]() mutable -> sample_t { return *s++; };
543+
else
544+
reader = [s, count = m_source_divide]() mutable -> sample_t { sample_t sm = 0; for(u32 i=0; i != count; i++) { sm += *s++; } return sm / count; };
545+
546+
phase <<= 12;
547+
548+
sample_t s0 = reader();
549+
sample_t s1 = reader();
550+
sample_t s2 = reader();
551+
sample_t s3 = reader();
552+
553+
s16 *d = dest.data() + destc;
554+
for(u32 sample = 0; sample != samples; sample++) {
555+
u32 cphase = phase >> 12;
556+
*d = gain * (- s0 * interpolation_table[0][0x1000-cphase] + s1 * interpolation_table[1][0x1000-cphase] + s2 * interpolation_table[1][cphase] - s3 * interpolation_table[0][cphase]);
557+
d += dchannels;
558+
559+
phase += m_step;
560+
if(phase & 0x1000000) {
561+
phase &= 0xffffff;
562+
s0 = s1;
563+
s1 = s2;
564+
s2 = s3;
565+
s3 = reader();
566+
}
567+
}
568+
}
569+
570+
void audio_resampler_lofi::apply_add(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const
571+
{
572+
u32 seconds = dest_sample / m_ft;
573+
u32 dsamp = dest_sample % m_ft;
574+
u64 ssamp = (u64(dsamp) * m_fs * 0x1000) / m_ft;
575+
u64 ssample = (ssamp >> 12) + u64(m_fs) * seconds;
576+
u32 phase = ssamp & 0xfff;
577+
if(m_source_divide > 1) {
578+
u32 delta = ssample % m_source_divide;
579+
phase = (phase | (delta << 12)) / m_source_divide;
580+
ssample -= delta;
581+
}
582+
583+
gain *= 32768;
584+
585+
// We're getting 2 samples latency, which is small enough
586+
587+
ssample -= 4*m_source_divide;
588+
589+
const sample_t *s = src.ptrs(srcc, ssample - src.sync_sample());
590+
591+
std::function<sample_t()> reader;
592+
if(m_source_divide == 1)
593+
reader = [s]() mutable -> sample_t { return *s++; };
594+
else
595+
reader = [s, count = m_source_divide]() mutable -> sample_t { sample_t sm = 0; for(u32 i=0; i != count; i++) { sm += *s++; } return sm / count; };
596+
597+
phase <<= 12;
598+
599+
sample_t s0 = reader();
600+
sample_t s1 = reader();
601+
sample_t s2 = reader();
602+
sample_t s3 = reader();
603+
604+
s16 *d = dest.data() + destc;
605+
for(u32 sample = 0; sample != samples; sample++) {
606+
u32 cphase = phase >> 12;
607+
*d += gain * (- s0 * interpolation_table[0][0x1000-cphase] + s1 * interpolation_table[1][0x1000-cphase] + s2 * interpolation_table[1][cphase] - s3 * interpolation_table[0][cphase]);
608+
d += dchannels;
609+
610+
phase += m_step;
611+
if(phase & 0x1000000) {
612+
phase &= 0xffffff;
613+
s0 = s1;
614+
s1 = s2;
615+
s2 = s3;
616+
s3 = reader();
617+
}
618+
}
442619
}

src/emu/resampler.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ class audio_resampler
2020
virtual u32 history_size() const = 0;
2121

2222
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const = 0;
23-
virtual void apply(const emu::detail::output_buffer_interleaved<s16> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const = 0;
24-
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const = 0;
23+
virtual void apply(const emu::detail::output_buffer_interleaved<s16> &src, sound_stream &dest, u32 srcc, u32 destc, float gain) const = 0;
24+
virtual void apply_copy(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const = 0;
25+
virtual void apply_add(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const = 0;
2526
};
2627

2728
class audio_resampler_hq : public audio_resampler
@@ -33,8 +34,9 @@ class audio_resampler_hq : public audio_resampler
3334
virtual u32 history_size() const override;
3435

3536
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
36-
virtual void apply(const emu::detail::output_buffer_interleaved<s16> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
37-
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
37+
virtual void apply(const emu::detail::output_buffer_interleaved<s16> &src, sound_stream &dest, u32 srcc, u32 destc, float gain) const override;
38+
virtual void apply_copy(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
39+
virtual void apply_add(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
3840

3941
private:
4042
u32 m_order_per_lane, m_ftm, m_fsm, m_ft, m_fs, m_delta, m_skip, m_phases, m_phase_shift;
@@ -53,8 +55,9 @@ class audio_resampler_lofi : public audio_resampler
5355
virtual u32 history_size() const override;
5456

5557
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
56-
virtual void apply(const emu::detail::output_buffer_interleaved<s16> &src, std::vector<sample_t> &dest, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
57-
virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
58+
virtual void apply(const emu::detail::output_buffer_interleaved<s16> &src, sound_stream &dest, u32 srcc, u32 destc, float gain) const override;
59+
virtual void apply_copy(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
60+
virtual void apply_add(const emu::detail::output_buffer_flat<sample_t> &src, std::vector<s16> &dest, u32 destc, int dchannels, u64 dest_sample, u32 srcc, float gain, u32 samples) const override;
5861

5962
private:
6063
static const std::array<std::array<float, 0x1001>, 2> interpolation_table;

0 commit comments

Comments
 (0)