timidity/resample.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 01 Jun 2013 22:30:04 -0700
changeset 627 438fb12df34f
parent 518 8bc9b5fd2aae
child 782 e7d3a8f73e88
permissions -rw-r--r--
Updated iOS project to include OGG support directly
slouken@0
     1
/*
slouken@0
     2
    TiMidity -- Experimental MIDI to WAVE converter
slouken@0
     3
    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
slouken@0
     4
slouken@0
     5
    This program is free software; you can redistribute it and/or modify
slouken@518
     6
    it under the terms of the Perl Artistic License, available in COPYING.
slouken@518
     7
 */
slouken@0
     8
slouken@0
     9
#include <math.h>
slouken@0
    10
#include <stdio.h>
slouken@95
    11
#include <stdlib.h>
slouken@0
    12
slouken@0
    13
#include "config.h"
slouken@0
    14
#include "common.h"
slouken@0
    15
#include "instrum.h"
slouken@0
    16
#include "playmidi.h"
slouken@0
    17
#include "output.h"
slouken@319
    18
#include "ctrlmode.h"
slouken@0
    19
#include "tables.h"
slouken@0
    20
#include "resample.h"
slouken@0
    21
slouken@0
    22
#ifdef LINEAR_INTERPOLATION
slouken@0
    23
# if defined(LOOKUP_HACK) && defined(LOOKUP_INTERPOLATION)
slouken@0
    24
#   define RESAMPLATION \
slouken@0
    25
       v1=src[ofs>>FRACTION_BITS];\
slouken@0
    26
       v2=src[(ofs>>FRACTION_BITS)+1];\
slouken@310
    27
       *dest++ = (resample_t)(v1 + (iplookup[(((v2-v1)<<5) & 0x03FE0) | \
slouken@310
    28
           ((ofs & FRACTION_MASK) >> (FRACTION_BITS-5))]));
slouken@0
    29
# else
slouken@0
    30
#   define RESAMPLATION \
slouken@0
    31
      v1=src[ofs>>FRACTION_BITS];\
slouken@0
    32
      v2=src[(ofs>>FRACTION_BITS)+1];\
slouken@310
    33
      *dest++ = (resample_t)(v1 + (((v2-v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS));
slouken@0
    34
# endif
slouken@0
    35
#  define INTERPVARS sample_t v1, v2
slouken@0
    36
#else
slouken@0
    37
/* Earplugs recommended for maximum listening enjoyment */
slouken@310
    38
#  define RESAMPLATION *dest++ = src[ofs>>FRACTION_BITS];
slouken@0
    39
#  define INTERPVARS
slouken@0
    40
#endif
slouken@0
    41
slouken@0
    42
#define FINALINTERP if (ofs == le) *dest++=src[ofs>>FRACTION_BITS];
slouken@0
    43
/* So it isn't interpolation. At least it's final. */
slouken@0
    44
slouken@245
    45
extern resample_t *resample_buffer;
slouken@0
    46
slouken@0
    47
/*************** resampling with fixed increment *****************/
slouken@0
    48
slouken@245
    49
static resample_t *rs_plain(int v, int32 *countptr)
slouken@0
    50
{
slouken@0
    51
slouken@0
    52
  /* Play sample until end, then free the voice. */
slouken@0
    53
slouken@0
    54
  INTERPVARS;
slouken@0
    55
  Voice 
slouken@0
    56
    *vp=&voice[v];
slouken@245
    57
  resample_t 
slouken@245
    58
    *dest=resample_buffer;
slouken@0
    59
  sample_t 
slouken@0
    60
    *src=vp->sample->data;
slouken@0
    61
  int32 
slouken@0
    62
    ofs=vp->sample_offset,
slouken@0
    63
    incr=vp->sample_increment,
slouken@0
    64
    le=vp->sample->data_length,
slouken@0
    65
    count=*countptr;
slouken@0
    66
slouken@0
    67
#ifdef PRECALC_LOOPS
slouken@245
    68
  int32 i, j;
slouken@0
    69
slouken@0
    70
  if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
slouken@0
    71
slouken@0
    72
  /* Precalc how many times we should go through the loop.
slouken@0
    73
     NOTE: Assumes that incr > 0 and that ofs <= le */
slouken@0
    74
  i = (le - ofs) / incr + 1;
slouken@0
    75
slouken@0
    76
  if (i > count)
slouken@0
    77
    {
slouken@0
    78
      i = count;
slouken@0
    79
      count = 0;
slouken@0
    80
    } 
slouken@0
    81
  else count -= i;
slouken@0
    82
slouken@245
    83
  for(j = 0; j < i; j++)
slouken@0
    84
    {
slouken@0
    85
      RESAMPLATION;
slouken@0
    86
      ofs += incr;
slouken@0
    87
    }
slouken@0
    88
slouken@0
    89
  if (ofs >= le) 
slouken@0
    90
    {
slouken@0
    91
      FINALINTERP;
slouken@0
    92
      vp->status=VOICE_FREE;
slouken@0
    93
      ctl->note(v);
slouken@0
    94
      *countptr-=count+1;
slouken@0
    95
    }
slouken@0
    96
slouken@0
    97
#else /* PRECALC_LOOPS */
slouken@0
    98
    while (count--)
slouken@0
    99
    {
slouken@0
   100
      RESAMPLATION;
slouken@0
   101
      ofs += incr;
slouken@0
   102
      if (ofs >= le)
slouken@0
   103
	{
slouken@0
   104
	  FINALINTERP;
slouken@0
   105
	  vp->status=VOICE_FREE;
slouken@0
   106
 	  ctl->note(v);
slouken@0
   107
	  *countptr-=count+1;
slouken@0
   108
	  break;
slouken@0
   109
	}
slouken@0
   110
    }
slouken@0
   111
#endif /* PRECALC_LOOPS */
slouken@0
   112
  
slouken@0
   113
  vp->sample_offset=ofs; /* Update offset */
slouken@0
   114
  return resample_buffer;
slouken@0
   115
}
slouken@0
   116
slouken@245
   117
static resample_t *rs_loop(Voice *vp, int32 count)
slouken@0
   118
{
slouken@0
   119
slouken@0
   120
  /* Play sample until end-of-loop, skip back and continue. */
slouken@0
   121
slouken@0
   122
  INTERPVARS;
slouken@0
   123
  int32 
slouken@0
   124
    ofs=vp->sample_offset, 
slouken@0
   125
    incr=vp->sample_increment,
slouken@0
   126
    le=vp->sample->loop_end, 
slouken@0
   127
    ll=le - vp->sample->loop_start;
slouken@245
   128
  resample_t
slouken@245
   129
    *dest=resample_buffer;
slouken@0
   130
  sample_t
slouken@0
   131
    *src=vp->sample->data;
slouken@0
   132
slouken@0
   133
#ifdef PRECALC_LOOPS
slouken@0
   134
  int32 i;
slouken@245
   135
 
slouken@245
   136
  if (ofs < 0 || le < 0) return resample_buffer;
slouken@245
   137
slouken@0
   138
  while (count) 
slouken@0
   139
    {
slouken@0
   140
      if (ofs >= le)
slouken@0
   141
	/* NOTE: Assumes that ll > incr and that incr > 0. */
slouken@0
   142
	ofs -= ll;
slouken@0
   143
      /* Precalc how many times we should go through the loop */
slouken@0
   144
      i = (le - ofs) / incr + 1;
slouken@0
   145
      if (i > count) 
slouken@0
   146
	{
slouken@0
   147
	  i = count;
slouken@0
   148
	  count = 0;
slouken@0
   149
	} 
slouken@0
   150
      else count -= i;
slouken@245
   151
      if (i > 0)
slouken@0
   152
      while (i--) 
slouken@0
   153
	{
slouken@0
   154
	  RESAMPLATION;
slouken@0
   155
	  ofs += incr;
slouken@0
   156
	}
slouken@0
   157
    }
slouken@0
   158
#else
slouken@0
   159
  while (count--)
slouken@0
   160
    {
slouken@0
   161
      RESAMPLATION;
slouken@0
   162
      ofs += incr;
slouken@0
   163
      if (ofs>=le)
slouken@0
   164
	ofs -= ll; /* Hopefully the loop is longer than an increment. */
slouken@0
   165
    }
slouken@0
   166
#endif
slouken@0
   167
slouken@0
   168
  vp->sample_offset=ofs; /* Update offset */
slouken@0
   169
  return resample_buffer;
slouken@0
   170
}
slouken@0
   171
slouken@245
   172
static resample_t *rs_bidir(Voice *vp, int32 count)
slouken@0
   173
{
slouken@0
   174
  INTERPVARS;
slouken@0
   175
  int32 
slouken@0
   176
    ofs=vp->sample_offset,
slouken@0
   177
    incr=vp->sample_increment,
slouken@0
   178
    le=vp->sample->loop_end,
slouken@0
   179
    ls=vp->sample->loop_start;
slouken@245
   180
  resample_t 
slouken@245
   181
    *dest=resample_buffer; 
slouken@0
   182
  sample_t 
slouken@0
   183
    *src=vp->sample->data;
slouken@0
   184
slouken@0
   185
#ifdef PRECALC_LOOPS
slouken@0
   186
  int32
slouken@0
   187
    le2 = le<<1, 
slouken@0
   188
    ls2 = ls<<1,
slouken@0
   189
    i;
slouken@0
   190
  /* Play normally until inside the loop region */
slouken@0
   191
slouken@0
   192
  if (ofs <= ls) 
slouken@0
   193
    {
slouken@0
   194
      /* NOTE: Assumes that incr > 0, which is NOT always the case
slouken@0
   195
	 when doing bidirectional looping.  I have yet to see a case
slouken@0
   196
	 where both ofs <= ls AND incr < 0, however. */
slouken@0
   197
      i = (ls - ofs) / incr + 1;
slouken@0
   198
      if (i > count) 
slouken@0
   199
	{
slouken@0
   200
	  i = count;
slouken@0
   201
	  count = 0;
slouken@0
   202
	} 
slouken@0
   203
      else count -= i;
slouken@0
   204
      while (i--) 
slouken@0
   205
	{
slouken@0
   206
	  RESAMPLATION;
slouken@0
   207
	  ofs += incr;
slouken@0
   208
	}
slouken@0
   209
    }
slouken@0
   210
slouken@0
   211
  /* Then do the bidirectional looping */
slouken@0
   212
  
slouken@0
   213
  while(count) 
slouken@0
   214
    {
slouken@0
   215
      /* Precalc how many times we should go through the loop */
slouken@0
   216
      i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
slouken@0
   217
      if (i > count) 
slouken@0
   218
	{
slouken@0
   219
	  i = count;
slouken@0
   220
	  count = 0;
slouken@0
   221
	} 
slouken@0
   222
      else count -= i;
slouken@0
   223
      while (i--) 
slouken@0
   224
	{
slouken@0
   225
	  RESAMPLATION;
slouken@0
   226
	  ofs += incr;
slouken@0
   227
	}
slouken@0
   228
      if (ofs>=le) 
slouken@0
   229
	{
slouken@0
   230
	  /* fold the overshoot back in */
slouken@0
   231
	  ofs = le2 - ofs;
slouken@0
   232
	  incr *= -1;
slouken@0
   233
	} 
slouken@0
   234
      else if (ofs <= ls) 
slouken@0
   235
	{
slouken@0
   236
	  ofs = ls2 - ofs;
slouken@0
   237
	  incr *= -1;
slouken@0
   238
	}
slouken@0
   239
    }
slouken@0
   240
slouken@0
   241
#else /* PRECALC_LOOPS */
slouken@0
   242
  /* Play normally until inside the loop region */
slouken@0
   243
slouken@0
   244
  if (ofs < ls)
slouken@0
   245
    {
slouken@0
   246
      while (count--)
slouken@0
   247
	{
slouken@0
   248
	  RESAMPLATION;
slouken@0
   249
	  ofs += incr;
slouken@0
   250
	  if (ofs>=ls)
slouken@0
   251
	    break;
slouken@0
   252
	}
slouken@0
   253
    }
slouken@0
   254
slouken@0
   255
  /* Then do the bidirectional looping */
slouken@0
   256
slouken@0
   257
  if (count>0)
slouken@0
   258
    while (count--)
slouken@0
   259
      {
slouken@0
   260
	RESAMPLATION;
slouken@0
   261
	ofs += incr;
slouken@0
   262
	if (ofs>=le)
slouken@0
   263
	  {
slouken@0
   264
	    /* fold the overshoot back in */
slouken@0
   265
	    ofs = le - (ofs - le);
slouken@0
   266
	    incr = -incr;
slouken@0
   267
	  }
slouken@0
   268
	else if (ofs <= ls)
slouken@0
   269
	  {
slouken@0
   270
	    ofs = ls + (ls - ofs);
slouken@0
   271
	    incr = -incr;
slouken@0
   272
	  }
slouken@0
   273
      }  
slouken@0
   274
#endif /* PRECALC_LOOPS */
slouken@0
   275
  vp->sample_increment=incr;
slouken@0
   276
  vp->sample_offset=ofs; /* Update offset */
slouken@0
   277
  return resample_buffer;
slouken@0
   278
}
slouken@0
   279
slouken@0
   280
/*********************** vibrato versions ***************************/
slouken@0
   281
slouken@0
   282
/* We only need to compute one half of the vibrato sine cycle */
slouken@0
   283
static int vib_phase_to_inc_ptr(int phase)
slouken@0
   284
{
slouken@0
   285
  if (phase < VIBRATO_SAMPLE_INCREMENTS/2)
slouken@0
   286
    return VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
slouken@0
   287
  else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)
slouken@0
   288
    return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
slouken@0
   289
  else
slouken@0
   290
    return phase-VIBRATO_SAMPLE_INCREMENTS/2;
slouken@0
   291
}
slouken@0
   292
slouken@0
   293
static int32 update_vibrato(Voice *vp, int sign)
slouken@0
   294
{
slouken@0
   295
  int32 depth;
slouken@0
   296
  int phase, pb;
slouken@0
   297
  double a;
slouken@0
   298
slouken@0
   299
  if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1)
slouken@0
   300
    vp->vibrato_phase=0;
slouken@0
   301
  phase=vib_phase_to_inc_ptr(vp->vibrato_phase);
slouken@0
   302
  
slouken@0
   303
  if (vp->vibrato_sample_increment[phase])
slouken@0
   304
    {
slouken@0
   305
      if (sign)
slouken@0
   306
	return -vp->vibrato_sample_increment[phase];
slouken@0
   307
      else
slouken@0
   308
	return vp->vibrato_sample_increment[phase];
slouken@0
   309
    }
slouken@0
   310
slouken@0
   311
  /* Need to compute this sample increment. */
slouken@0
   312
    
slouken@0
   313
  depth=vp->sample->vibrato_depth<<7;
slouken@0
   314
slouken@0
   315
  if (vp->vibrato_sweep)
slouken@0
   316
    {
slouken@0
   317
      /* Need to update sweep */
slouken@0
   318
      vp->vibrato_sweep_position += vp->vibrato_sweep;
slouken@0
   319
      if (vp->vibrato_sweep_position >= (1<<SWEEP_SHIFT))
slouken@0
   320
	vp->vibrato_sweep=0;
slouken@0
   321
      else
slouken@0
   322
	{
slouken@0
   323
	  /* Adjust depth */
slouken@0
   324
	  depth *= vp->vibrato_sweep_position;
slouken@0
   325
	  depth >>= SWEEP_SHIFT;
slouken@0
   326
	}
slouken@0
   327
    }
slouken@0
   328
slouken@0
   329
  a = FSCALE(((double)(vp->sample->sample_rate) *
slouken@0
   330
	      (double)(vp->frequency)) /
slouken@0
   331
	     ((double)(vp->sample->root_freq) *
slouken@0
   332
	      (double)(play_mode->rate)),
slouken@0
   333
	     FRACTION_BITS);
slouken@0
   334
slouken@0
   335
  pb=(int)((sine(vp->vibrato_phase * 
slouken@0
   336
		 (SINE_CYCLE_LENGTH/(2*VIBRATO_SAMPLE_INCREMENTS)))
slouken@0
   337
	    * (double)(depth) * VIBRATO_AMPLITUDE_TUNING));
slouken@0
   338
slouken@0
   339
  if (pb<0)
slouken@0
   340
    {
slouken@0
   341
      pb=-pb;
slouken@0
   342
      a /= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];
slouken@0
   343
    }
slouken@0
   344
  else
slouken@0
   345
    a *= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];
slouken@0
   346
  
slouken@0
   347
  /* If the sweep's over, we can store the newly computed sample_increment */
slouken@0
   348
  if (!vp->vibrato_sweep)
slouken@0
   349
    vp->vibrato_sample_increment[phase]=(int32) a;
slouken@0
   350
slouken@0
   351
  if (sign)
slouken@0
   352
    a = -a; /* need to preserve the loop direction */
slouken@0
   353
slouken@0
   354
  return (int32) a;
slouken@0
   355
}
slouken@0
   356
slouken@245
   357
static resample_t *rs_vib_plain(int v, int32 *countptr)
slouken@0
   358
{
slouken@0
   359
slouken@0
   360
  /* Play sample until end, then free the voice. */
slouken@0
   361
slouken@0
   362
  INTERPVARS;
slouken@0
   363
  Voice *vp=&voice[v];
slouken@245
   364
  resample_t 
slouken@245
   365
    *dest=resample_buffer; 
slouken@0
   366
  sample_t 
slouken@0
   367
    *src=vp->sample->data;
slouken@0
   368
  int32 
slouken@0
   369
    le=vp->sample->data_length,
slouken@0
   370
    ofs=vp->sample_offset, 
slouken@0
   371
    incr=vp->sample_increment, 
slouken@0
   372
    count=*countptr;
slouken@0
   373
  int 
slouken@0
   374
    cc=vp->vibrato_control_counter;
slouken@0
   375
slouken@0
   376
  /* This has never been tested */
slouken@0
   377
slouken@0
   378
  if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
slouken@0
   379
slouken@0
   380
  while (count--)
slouken@0
   381
    {
slouken@0
   382
      if (!cc--)
slouken@0
   383
	{
slouken@0
   384
	  cc=vp->vibrato_control_ratio;
slouken@0
   385
	  incr=update_vibrato(vp, 0);
slouken@0
   386
	}
slouken@0
   387
      RESAMPLATION;
slouken@0
   388
      ofs += incr;
slouken@0
   389
      if (ofs >= le)
slouken@0
   390
	{
slouken@0
   391
	  FINALINTERP;
slouken@0
   392
	  vp->status=VOICE_FREE;
slouken@0
   393
 	  ctl->note(v);
slouken@0
   394
	  *countptr-=count+1;
slouken@0
   395
	  break;
slouken@0
   396
	}
slouken@0
   397
    }
slouken@0
   398
  
slouken@0
   399
  vp->vibrato_control_counter=cc;
slouken@0
   400
  vp->sample_increment=incr;
slouken@0
   401
  vp->sample_offset=ofs; /* Update offset */
slouken@0
   402
  return resample_buffer;
slouken@0
   403
}
slouken@0
   404
slouken@245
   405
static resample_t *rs_vib_loop(Voice *vp, int32 count)
slouken@0
   406
{
slouken@0
   407
slouken@0
   408
  /* Play sample until end-of-loop, skip back and continue. */
slouken@0
   409
  
slouken@0
   410
  INTERPVARS;
slouken@0
   411
  int32 
slouken@0
   412
    ofs=vp->sample_offset, 
slouken@0
   413
    incr=vp->sample_increment, 
slouken@0
   414
    le=vp->sample->loop_end,
slouken@0
   415
    ll=le - vp->sample->loop_start;
slouken@245
   416
  resample_t 
slouken@245
   417
    *dest=resample_buffer; 
slouken@0
   418
  sample_t 
slouken@0
   419
    *src=vp->sample->data;
slouken@0
   420
  int 
slouken@0
   421
    cc=vp->vibrato_control_counter;
slouken@0
   422
slouken@0
   423
#ifdef PRECALC_LOOPS
slouken@0
   424
  int32 i;
slouken@0
   425
  int
slouken@0
   426
    vibflag=0;
slouken@0
   427
slouken@0
   428
  while (count) 
slouken@0
   429
    {
slouken@0
   430
      /* Hopefully the loop is longer than an increment */
slouken@0
   431
      if(ofs >= le)
slouken@0
   432
	ofs -= ll;
slouken@0
   433
      /* Precalc how many times to go through the loop, taking
slouken@0
   434
	 the vibrato control ratio into account this time. */
slouken@0
   435
      i = (le - ofs) / incr + 1;
slouken@0
   436
      if(i > count) i = count;
slouken@0
   437
      if(i > cc)
slouken@0
   438
	{
slouken@0
   439
	  i = cc;
slouken@0
   440
	  vibflag = 1;
slouken@0
   441
	} 
slouken@0
   442
      else cc -= i;
slouken@0
   443
      count -= i;
slouken@0
   444
      while(i--) 
slouken@0
   445
	{
slouken@0
   446
	  RESAMPLATION;
slouken@0
   447
	  ofs += incr;
slouken@0
   448
	}
slouken@0
   449
      if(vibflag) 
slouken@0
   450
	{
slouken@0
   451
	  cc = vp->vibrato_control_ratio;
slouken@0
   452
	  incr = update_vibrato(vp, 0);
slouken@0
   453
	  vibflag = 0;
slouken@0
   454
	}
slouken@0
   455
    }
slouken@0
   456
slouken@0
   457
#else /* PRECALC_LOOPS */
slouken@0
   458
  while (count--)
slouken@0
   459
    {
slouken@0
   460
      if (!cc--)
slouken@0
   461
	{
slouken@0
   462
	  cc=vp->vibrato_control_ratio;
slouken@0
   463
	  incr=update_vibrato(vp, 0);
slouken@0
   464
	}
slouken@0
   465
      RESAMPLATION;
slouken@0
   466
      ofs += incr;
slouken@0
   467
      if (ofs>=le)
slouken@0
   468
	ofs -= ll; /* Hopefully the loop is longer than an increment. */
slouken@0
   469
    }
slouken@0
   470
#endif /* PRECALC_LOOPS */
slouken@0
   471
slouken@0
   472
  vp->vibrato_control_counter=cc;
slouken@0
   473
  vp->sample_increment=incr;
slouken@0
   474
  vp->sample_offset=ofs; /* Update offset */
slouken@0
   475
  return resample_buffer;
slouken@0
   476
}
slouken@0
   477
slouken@245
   478
static resample_t *rs_vib_bidir(Voice *vp, int32 count)
slouken@0
   479
{
slouken@0
   480
  INTERPVARS;
slouken@0
   481
  int32 
slouken@0
   482
    ofs=vp->sample_offset, 
slouken@0
   483
    incr=vp->sample_increment,
slouken@0
   484
    le=vp->sample->loop_end, 
slouken@0
   485
    ls=vp->sample->loop_start;
slouken@245
   486
  resample_t 
slouken@245
   487
    *dest=resample_buffer; 
slouken@0
   488
  sample_t 
slouken@0
   489
    *src=vp->sample->data;
slouken@0
   490
  int 
slouken@0
   491
    cc=vp->vibrato_control_counter;
slouken@0
   492
slouken@0
   493
#ifdef PRECALC_LOOPS
slouken@0
   494
  int32
slouken@0
   495
    le2=le<<1,
slouken@0
   496
    ls2=ls<<1,
slouken@0
   497
    i;
slouken@0
   498
  int
slouken@0
   499
    vibflag = 0;
slouken@0
   500
slouken@0
   501
  /* Play normally until inside the loop region */
slouken@0
   502
  while (count && (ofs <= ls)) 
slouken@0
   503
    {
slouken@0
   504
      i = (ls - ofs) / incr + 1;
slouken@0
   505
      if (i > count) i = count;
slouken@0
   506
      if (i > cc) 
slouken@0
   507
	{
slouken@0
   508
	  i = cc;
slouken@0
   509
	  vibflag = 1;
slouken@0
   510
	} 
slouken@0
   511
      else cc -= i;
slouken@0
   512
      count -= i;
slouken@0
   513
      while (i--) 
slouken@0
   514
	{
slouken@0
   515
	  RESAMPLATION;
slouken@0
   516
	  ofs += incr;
slouken@0
   517
	}
slouken@0
   518
      if (vibflag) 
slouken@0
   519
	{
slouken@0
   520
	  cc = vp->vibrato_control_ratio;
slouken@0
   521
	  incr = update_vibrato(vp, 0);
slouken@0
   522
	  vibflag = 0;
slouken@0
   523
	}
slouken@0
   524
    }
slouken@0
   525
  
slouken@0
   526
  /* Then do the bidirectional looping */
slouken@0
   527
slouken@0
   528
  while (count) 
slouken@0
   529
    {
slouken@0
   530
      /* Precalc how many times we should go through the loop */
slouken@0
   531
      i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
slouken@0
   532
      if(i > count) i = count;
slouken@0
   533
      if(i > cc) 
slouken@0
   534
	{
slouken@0
   535
	  i = cc;
slouken@0
   536
	  vibflag = 1;
slouken@0
   537
	} 
slouken@0
   538
      else cc -= i;
slouken@0
   539
      count -= i;
slouken@0
   540
      while (i--) 
slouken@0
   541
	{
slouken@0
   542
	  RESAMPLATION;
slouken@0
   543
	  ofs += incr;
slouken@0
   544
	}
slouken@0
   545
      if (vibflag) 
slouken@0
   546
	{
slouken@0
   547
	  cc = vp->vibrato_control_ratio;
slouken@0
   548
	  incr = update_vibrato(vp, (incr < 0));
slouken@0
   549
	  vibflag = 0;
slouken@0
   550
	}
slouken@0
   551
      if (ofs >= le) 
slouken@0
   552
	{
slouken@0
   553
	  /* fold the overshoot back in */
slouken@0
   554
	  ofs = le2 - ofs;
slouken@0
   555
	  incr *= -1;
slouken@0
   556
	} 
slouken@0
   557
      else if (ofs <= ls) 
slouken@0
   558
	{
slouken@0
   559
	  ofs = ls2 - ofs;
slouken@0
   560
	  incr *= -1;
slouken@0
   561
	}
slouken@0
   562
    }
slouken@0
   563
slouken@0
   564
#else /* PRECALC_LOOPS */
slouken@0
   565
  /* Play normally until inside the loop region */
slouken@0
   566
slouken@0
   567
  if (ofs < ls)
slouken@0
   568
    {
slouken@0
   569
      while (count--)
slouken@0
   570
	{
slouken@0
   571
	  if (!cc--)
slouken@0
   572
	    {
slouken@0
   573
	      cc=vp->vibrato_control_ratio;
slouken@0
   574
	      incr=update_vibrato(vp, 0);
slouken@0
   575
	    }
slouken@0
   576
	  RESAMPLATION;
slouken@0
   577
	  ofs += incr;
slouken@0
   578
	  if (ofs>=ls)
slouken@0
   579
	    break;
slouken@0
   580
	}
slouken@0
   581
    }
slouken@0
   582
slouken@0
   583
  /* Then do the bidirectional looping */
slouken@0
   584
slouken@0
   585
  if (count>0)
slouken@0
   586
    while (count--)
slouken@0
   587
      {
slouken@0
   588
	if (!cc--)
slouken@0
   589
	  {
slouken@0
   590
	    cc=vp->vibrato_control_ratio;
slouken@0
   591
	    incr=update_vibrato(vp, (incr < 0));
slouken@0
   592
	  }
slouken@0
   593
	RESAMPLATION;
slouken@0
   594
	ofs += incr;
slouken@0
   595
	if (ofs>=le)
slouken@0
   596
	  {
slouken@0
   597
	    /* fold the overshoot back in */
slouken@0
   598
	    ofs = le - (ofs - le);
slouken@0
   599
	    incr = -incr;
slouken@0
   600
	  }
slouken@0
   601
	else if (ofs <= ls)
slouken@0
   602
	  {
slouken@0
   603
	    ofs = ls + (ls - ofs);
slouken@0
   604
	    incr = -incr;
slouken@0
   605
	  }
slouken@0
   606
      }
slouken@0
   607
#endif /* PRECALC_LOOPS */
slouken@0
   608
slouken@0
   609
  vp->vibrato_control_counter=cc;
slouken@0
   610
  vp->sample_increment=incr;
slouken@0
   611
  vp->sample_offset=ofs; /* Update offset */
slouken@0
   612
  return resample_buffer;
slouken@0
   613
}
slouken@0
   614
slouken@245
   615
resample_t *resample_voice(int v, int32 *countptr)
slouken@0
   616
{
slouken@0
   617
  int32 ofs;
slouken@0
   618
  uint8 modes;
slouken@0
   619
  Voice *vp=&voice[v];
slouken@0
   620
  
slouken@0
   621
  if (!(vp->sample->sample_rate))
slouken@0
   622
    {
slouken@0
   623
      /* Pre-resampled data -- just update the offset and check if
slouken@0
   624
         we're out of data. */
slouken@0
   625
      ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use
slouken@0
   626
						 FRACTION_BITS here... */
slouken@0
   627
      if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs)
slouken@0
   628
	{
slouken@0
   629
	  /* Note finished. Free the voice. */
slouken@0
   630
	  vp->status = VOICE_FREE;
slouken@0
   631
	  ctl->note(v);
slouken@0
   632
	  
slouken@0
   633
	  /* Let the caller know how much data we had left */
slouken@0
   634
	  *countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs;
slouken@0
   635
	}
slouken@0
   636
      else
slouken@0
   637
	vp->sample_offset += *countptr << FRACTION_BITS;
slouken@0
   638
      
slouken@245
   639
      return (resample_t *)vp->sample->data+ofs;
slouken@0
   640
    }
slouken@0
   641
slouken@0
   642
  /* Need to resample. Use the proper function. */
slouken@0
   643
  modes=vp->sample->modes;
slouken@0
   644
slouken@0
   645
  if (vp->vibrato_control_ratio)
slouken@0
   646
    {
slouken@0
   647
      if ((modes & MODES_LOOPING) &&
slouken@0
   648
	  ((modes & MODES_ENVELOPE) ||
slouken@0
   649
	   (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
slouken@0
   650
	{
slouken@0
   651
	  if (modes & MODES_PINGPONG)
slouken@0
   652
	    return rs_vib_bidir(vp, *countptr);
slouken@0
   653
	  else
slouken@0
   654
	    return rs_vib_loop(vp, *countptr);
slouken@0
   655
	}
slouken@0
   656
      else
slouken@0
   657
	return rs_vib_plain(v, countptr);
slouken@0
   658
    }
slouken@0
   659
  else
slouken@0
   660
    {
slouken@0
   661
      if ((modes & MODES_LOOPING) &&
slouken@0
   662
	  ((modes & MODES_ENVELOPE) ||
slouken@0
   663
	   (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
slouken@0
   664
	{
slouken@0
   665
	  if (modes & MODES_PINGPONG)
slouken@0
   666
	    return rs_bidir(vp, *countptr);
slouken@0
   667
	  else
slouken@0
   668
	    return rs_loop(vp, *countptr);
slouken@0
   669
	}
slouken@0
   670
      else
slouken@0
   671
	return rs_plain(v, countptr);
slouken@0
   672
    }
slouken@0
   673
}
slouken@0
   674
slouken@0
   675
void pre_resample(Sample * sp)
slouken@0
   676
{
slouken@0
   677
  double a, xdiff;
slouken@0
   678
  int32 incr, ofs, newlen, count;
slouken@245
   679
  int16 *src = (int16 *) sp->data;
slouken@245
   680
  resample_t *newdata, *dest;
slouken@0
   681
  int16 v1, v2, v3, v4, *vptr;
slouken@0
   682
  static const char note_name[12][3] =
slouken@0
   683
  {
slouken@0
   684
    "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
slouken@0
   685
  };
slouken@0
   686
slouken@0
   687
  ctl->cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",
slouken@0
   688
	    sp->note_to_use,
slouken@0
   689
	    note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);
slouken@0
   690
slouken@0
   691
  a = ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]) /
slouken@0
   692
    ((double) (sp->root_freq) * play_mode->rate);
slouken@245
   693
  if (a <= 0) return;
slouken@42
   694
  newlen = (int32)(sp->data_length / a);
slouken@245
   695
  if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE) return;
slouken@0
   696
  dest = newdata = safe_malloc(newlen >> (FRACTION_BITS - 1));
slouken@0
   697
slouken@0
   698
  count = (newlen >> FRACTION_BITS) - 1;
slouken@0
   699
  ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;
slouken@0
   700
slouken@0
   701
  if (--count)
slouken@0
   702
    *dest++ = src[0];
slouken@0
   703
slouken@0
   704
  /* Since we're pre-processing and this doesn't have to be done in
slouken@0
   705
     real-time, we go ahead and do the full sliding cubic interpolation. */
slouken@0
   706
  while (--count)
slouken@0
   707
    {
slouken@0
   708
      vptr = src + (ofs >> FRACTION_BITS);
slouken@348
   709
      v1 = (vptr == src) ? *vptr : *(vptr - 1);
slouken@0
   710
      v2 = *vptr;
slouken@0
   711
      v3 = *(vptr + 1);
slouken@0
   712
      v4 = *(vptr + 2);
slouken@0
   713
      xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS);
slouken@42
   714
      *dest++ = (int16)(v2 + (xdiff / 6.0) * (-2 * v1 - 3 * v2 + 6 * v3 - v4 +
slouken@42
   715
      xdiff * (3 * (v1 - 2 * v2 + v3) + xdiff * (-v1 + 3 * (v2 - v3) + v4))));
slouken@0
   716
      ofs += incr;
slouken@0
   717
    }
slouken@0
   718
slouken@0
   719
  if (ofs & FRACTION_MASK)
slouken@0
   720
    {
slouken@0
   721
      v1 = src[ofs >> FRACTION_BITS];
slouken@0
   722
      v2 = src[(ofs >> FRACTION_BITS) + 1];
slouken@310
   723
      *dest++ = (resample_t)(v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS));
slouken@0
   724
    }
slouken@0
   725
  else
slouken@0
   726
    *dest++ = src[ofs >> FRACTION_BITS];
slouken@0
   727
slouken@0
   728
  sp->data_length = newlen;
slouken@42
   729
  sp->loop_start = (int32)(sp->loop_start / a);
slouken@42
   730
  sp->loop_end = (int32)(sp->loop_end / a);
slouken@0
   731
  free(sp->data);
slouken@0
   732
  sp->data = (sample_t *) newdata;
slouken@0
   733
  sp->sample_rate = 0;
slouken@0
   734
}