Coverage Report

Created: 2026-08-14 07:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/contrib/contrib-build/game-music-emu/gme/Fir_Resampler.cpp
Line
Count
Source
1
// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
2
3
#include "Fir_Resampler.h"
4
5
#include <string.h>
6
#include <stdlib.h>
7
#include <stdio.h>
8
#include <math.h>
9
10
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
11
can redistribute it and/or modify it under the terms of the GNU Lesser
12
General Public License as published by the Free Software Foundation; either
13
version 2.1 of the License, or (at your option) any later version. This
14
module is distributed in the hope that it will be useful, but WITHOUT ANY
15
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17
details. You should have received a copy of the GNU Lesser General Public
18
License along with this module; if not, write to the Free Software Foundation,
19
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
20
21
#include "blargg_source.h"
22
23
#undef PI
24
17.7k
#define PI 3.1415926535897932384626433832795029
25
26
static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
27
    int count, short* out )
28
893
{
29
893
  double const maxh = 256;
30
893
  double const step = PI / maxh * spacing;
31
893
  double const to_w = maxh * 2 / width;
32
893
  double const pow_a_n = pow( rolloff, maxh );
33
893
  scale /= maxh * 2;
34
35
893
  double angle = (count / 2 - 1 + offset) * -step;
36
17.7k
  while ( count-- )
37
16.8k
  {
38
16.8k
    *out++ = 0;
39
16.8k
    double w = angle * to_w;
40
16.8k
    if ( fabs( w ) < PI )
41
16.5k
    {
42
16.5k
      double rolloff_cos_a = rolloff * cos( angle );
43
16.5k
      double num = 1 - rolloff_cos_a -
44
16.5k
          pow_a_n * cos( maxh * angle ) +
45
16.5k
          pow_a_n * rolloff * cos( (maxh - 1) * angle );
46
16.5k
      double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
47
16.5k
      double sinc = scale * num / den - scale;
48
49
16.5k
      out [-1] = (short) (cos( w ) * sinc + sinc);
50
16.5k
    }
51
16.8k
    angle += step;
52
16.8k
  }
53
893
}
54
55
Fir_Resampler_::Fir_Resampler_( int width, sample_t* impulses_ ) :
56
358
  width_( width ),
57
358
  write_offset( width * stereo - stereo ),
58
358
  impulses( impulses_ )
59
358
{
60
358
  write_pos = 0;
61
358
  res       = 1;
62
358
  imp_phase = 0;
63
358
  skip_bits = 0;
64
358
  step      = stereo;
65
358
  ratio_    = 1.0;
66
358
}
67
68
358
Fir_Resampler_::~Fir_Resampler_() { }
69
70
void Fir_Resampler_::clear()
71
1.23k
{
72
1.23k
  imp_phase = 0;
73
1.23k
  if ( buf.size() )
74
945
  {
75
945
    write_pos = &buf [write_offset];
76
945
    memset( buf.begin(), 0, write_offset * sizeof buf [0] );
77
945
  }
78
1.23k
}
79
80
blargg_err_t Fir_Resampler_::buffer_size( int new_size )
81
355
{
82
355
  RETURN_ERR( buf.resize( new_size + write_offset ) );
83
355
  clear();
84
355
  return 0;
85
355
}
86
87
double Fir_Resampler_::time_ratio( double new_factor, double rolloff, double gain )
88
363
{
89
363
  ratio_ = new_factor;
90
91
363
  double fstep = 0.0;
92
363
  {
93
363
    double least_error = 2;
94
363
    double pos = 0;
95
363
    res = -1;
96
11.9k
    for ( int r = 1; r <= max_res; r++ )
97
11.6k
    {
98
11.6k
      pos += ratio_;
99
11.6k
      double nearest = floor( pos + 0.5 );
100
11.6k
      double error = fabs( pos - nearest );
101
11.6k
      if ( error < least_error )
102
798
      {
103
798
        res = r;
104
798
        fstep = nearest / res;
105
798
        least_error = error;
106
798
      }
107
11.6k
    }
108
363
  }
109
110
363
  skip_bits = 0;
111
112
363
  step = stereo * (int) floor( fstep );
113
114
363
  ratio_ = fstep;
115
363
  fstep = fmod( fstep, 1.0 );
116
117
363
  double filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
118
363
  double pos = 0.0;
119
363
  input_per_cycle = 0;
120
1.25k
  for ( int i = 0; i < res; i++ )
121
893
  {
122
893
    gen_sinc( rolloff, int (width_ * filter + 1) & ~1, pos, filter,
123
893
        double (0x7FFF * gain * filter),
124
893
        (int) width_, impulses + i * width_ );
125
126
893
    pos += fstep;
127
893
    input_per_cycle += step;
128
893
    if ( pos >= 0.9999999 )
129
530
    {
130
530
      pos -= 1.0;
131
530
      skip_bits |= 1 << i;
132
530
      input_per_cycle++;
133
530
    }
134
893
  }
135
136
363
  clear();
137
138
363
  return ratio_;
139
363
}
140
141
int Fir_Resampler_::input_needed( int32_t output_count ) const
142
0
{
143
0
  int32_t input_count = 0;
144
145
0
  unsigned long skip = skip_bits >> imp_phase;
146
0
  int remain = res - imp_phase;
147
0
  while ( (output_count -= 2) > 0 )
148
0
  {
149
0
    input_count += step + (skip & 1) * stereo;
150
0
    skip >>= 1;
151
0
    if ( !--remain )
152
0
    {
153
0
      skip = skip_bits;
154
0
      remain = res;
155
0
    }
156
0
    output_count -= 2;
157
0
  }
158
159
0
  long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
160
0
  if ( input_extra < 0 )
161
0
    input_extra = 0;
162
0
  return input_extra;
163
0
}
164
165
int Fir_Resampler_::avail_( int32_t input_count ) const
166
0
{
167
0
  int cycle_count = input_count / input_per_cycle;
168
0
  int output_count = cycle_count * res * stereo;
169
0
  input_count -= cycle_count * input_per_cycle;
170
171
0
  uint32_t skip = skip_bits >> imp_phase;
172
0
  int remain = res - imp_phase;
173
0
  while ( input_count >= 0 )
174
0
  {
175
0
    input_count -= step + (skip & 1) * stereo;
176
0
    skip >>= 1;
177
0
    if ( !--remain )
178
0
    {
179
0
      skip = skip_bits;
180
0
      remain = res;
181
0
    }
182
0
    output_count += 2;
183
0
  }
184
0
  return output_count;
185
0
}
186
187
int Fir_Resampler_::skip_input( long count )
188
0
{
189
0
  int remain = write_pos - buf.begin();
190
0
  int max_count = remain - width_ * stereo;
191
0
  if ( max_count < 0 )
192
0
    max_count = 0;
193
0
  if ( count > max_count )
194
0
    count = max_count;
195
196
0
  remain -= count;
197
0
  write_pos = &buf [remain];
198
0
  memmove( buf.begin(), &buf [count], remain * sizeof buf [0] );
199
200
0
  return count;
201
0
}