mirror of
https://github.com/mpv-player/mpv
synced 2024-12-23 23:32:26 +00:00
Sync problem when using fractional resampling fixed + speed increased.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4172 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
47aa9aeb74
commit
f36628b8fe
@ -111,7 +111,7 @@
|
||||
#define SAVE_QUE(x)
|
||||
#define UPDATE_QUE(inm) \
|
||||
xi=(--xi)&(L-1); \
|
||||
x[xi]=x[xi+L]=*inm;
|
||||
x[xi]=x[xi+L]=*(inm);
|
||||
|
||||
#ifdef L4
|
||||
#define FIR(x,w,y) \
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "audio_plugin.h"
|
||||
#include "audio_plugin_internal.h"
|
||||
#include "afmt.h"
|
||||
//#include "../config.h"
|
||||
// #include "../config.h"
|
||||
|
||||
static ao_info_t info =
|
||||
{
|
||||
@ -46,15 +46,16 @@ LIBAO_PLUGIN_EXTERN(resample)
|
||||
memory usage. For now the filterlenght is choosen to 4 and without
|
||||
assembly optimization if no SSE is present.
|
||||
*/
|
||||
#ifdef HAVE_SSE
|
||||
|
||||
// #ifdef HAVE_SSE
|
||||
#define L8 1 // Filter bank type
|
||||
#define W W8 // Filter bank parameters
|
||||
#define L 8 // Filter length
|
||||
#else
|
||||
#define L4 1
|
||||
#define W W4
|
||||
#define L 4
|
||||
#endif
|
||||
// #else
|
||||
// #define L4 1
|
||||
// #define W W4
|
||||
// #define L 4
|
||||
// #endif
|
||||
|
||||
#define CH 6 // Max number of channels
|
||||
#define UP 128 /* Up sampling factor. Increasing this value will
|
||||
@ -73,12 +74,11 @@ typedef struct pl_resample_s
|
||||
uint16_t up; // Up sampling factor
|
||||
int channels; // Number of channels
|
||||
int len; // Lenght of buffer
|
||||
int bypass; // Bypass this plugin
|
||||
int16_t ws[UP*L]; // List of all available filters
|
||||
int16_t xs[CH][L*2]; // Circular buffers
|
||||
} pl_resample_t;
|
||||
|
||||
static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,0,W};
|
||||
static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,W};
|
||||
|
||||
// to set/get/query special features/parameters
|
||||
static int control(int cmd,int arg){
|
||||
@ -117,11 +117,7 @@ static int init(){
|
||||
return 0;
|
||||
}
|
||||
pl_resample.dn=(int)(0.5+((float)(fin*pl_resample.up))/((float)fout));
|
||||
if(pl_resample.dn == pl_resample.up){
|
||||
fprintf(stderr,"[pl_resample] Fin is too close to fout no conversion is needed.\n");
|
||||
pl_resample.bypass=1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
pl_resample.channels=ao_plugin_data.channels;
|
||||
if(ao_plugin_data.channels>CH){
|
||||
fprintf(stderr,"[pl_resample] Too many channels, max is 6.\n");
|
||||
@ -155,12 +151,79 @@ static void reset(){
|
||||
// called for every block of data
|
||||
// FIXME: this routine needs to be optimized (it is probably possible to do a lot here)
|
||||
static int play(){
|
||||
if(pl_resample.up==pl_resample.dn){
|
||||
register int16_t* in = ((int16_t*)ao_plugin_data.data);
|
||||
register int16_t* end = in+ao_plugin_data.len/2;
|
||||
while(in < end) *in=(*in++)>>1;
|
||||
return 1;
|
||||
}
|
||||
if(pl_resample.up>pl_resample.dn)
|
||||
return upsample();
|
||||
if(pl_resample.up<pl_resample.dn)
|
||||
return downsample();
|
||||
}
|
||||
|
||||
int upsample(){
|
||||
static uint16_t pwi = 0; // Index for w
|
||||
static uint16_t pxi = 0; // Index for circular queue
|
||||
|
||||
uint16_t ci = pl_resample.channels; // Index for channels
|
||||
uint16_t nch = pl_resample.channels; // Number of channels
|
||||
uint16_t len = 0; // Number of input samples
|
||||
uint16_t inc = pl_resample.up/pl_resample.dn;
|
||||
uint16_t level = pl_resample.up%pl_resample.dn;
|
||||
uint16_t up = pl_resample.up;
|
||||
uint16_t dn = pl_resample.dn;
|
||||
|
||||
register int16_t* w = pl_resample.w;
|
||||
register uint16_t wi,xi; // Temporary indexes
|
||||
|
||||
// Index current channel
|
||||
while(ci--){
|
||||
// Temporary pointers
|
||||
register int16_t* x = pl_resample.xs[ci];
|
||||
register int16_t* in = ((int16_t*)ao_plugin_data.data)+ci;
|
||||
register int16_t* out = pl_resample.data+ci;
|
||||
int16_t* end = in+ao_plugin_data.len/2; // Block loop end
|
||||
|
||||
wi = pwi; xi = pxi;
|
||||
|
||||
LOAD_QUE(x);
|
||||
while(in < end){
|
||||
register uint16_t i = inc;
|
||||
if(wi<level) i++;
|
||||
|
||||
UPDATE_QUE(in);
|
||||
in+=nch;
|
||||
|
||||
while(i--){
|
||||
// Run the FIR filter
|
||||
FIR((&x[xi]),(&w[wi*L]),out);
|
||||
len++; out+=nch;
|
||||
// Update wi to point at the correct polyphase component
|
||||
wi=(wi+dn)%up;
|
||||
}
|
||||
}
|
||||
SAVE_QUE(x);
|
||||
}
|
||||
|
||||
// Save values that needs to be kept for next time
|
||||
pwi = wi;
|
||||
pxi = xi;
|
||||
|
||||
// Set new data
|
||||
ao_plugin_data.len=len*2;
|
||||
ao_plugin_data.data=pl_resample.data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int downsample(){
|
||||
static uint16_t pwi = 0; // Index for w
|
||||
static uint16_t pxi = 0; // Index for circular queue
|
||||
static uint16_t pi = 1; // Number of new samples to put in x queue
|
||||
|
||||
uint16_t ci = pl_resample.channels; // Index for channels
|
||||
uint16_t len = 0; // Number of output samples
|
||||
uint16_t len = 0; // Number of input samples
|
||||
uint16_t nch = pl_resample.channels; // Number of channels
|
||||
uint16_t inc = pl_resample.dn/pl_resample.up;
|
||||
uint16_t level = pl_resample.dn%pl_resample.up;
|
||||
@ -169,8 +232,6 @@ static int play(){
|
||||
|
||||
register uint16_t i,wi,xi; // Temporary indexes
|
||||
|
||||
if(pl_resample.bypass)
|
||||
return 1;
|
||||
|
||||
// Index current channel
|
||||
while(ci--){
|
||||
@ -183,33 +244,26 @@ static int play(){
|
||||
i = pi; wi = pwi; xi = pxi;
|
||||
|
||||
LOAD_QUE(x);
|
||||
if(0!=i) goto L1;
|
||||
while(in < end){
|
||||
// Update wi to point at the correct polyphase component
|
||||
wi=(wi+dn)%up;
|
||||
|
||||
/* Update circular buffer x. This loop will be updated 0 or 1 time
|
||||
for upsamling and inc or inc + 1 times for downsampling */
|
||||
if(wi<level) goto L3;
|
||||
if(0==i) goto L2;
|
||||
L1: i--;
|
||||
L3: UPDATE_QUE(in);
|
||||
in+=nch;
|
||||
if(in >= end) goto L2;
|
||||
if(i) goto L1;
|
||||
L2: if(i) goto L5;
|
||||
i=inc;
|
||||
UPDATE_QUE(in);
|
||||
in+=nch;
|
||||
|
||||
if(!--i){
|
||||
// Run the FIR filter
|
||||
FIR((&x[xi]),(&pl_resample.w[wi*L]),out);
|
||||
len++; out+=nch;
|
||||
|
||||
/* Get the correct polyphase component and the correct startpoint
|
||||
in the circular bufer and run the FIR filter */
|
||||
FIR((&x[xi]),(&pl_resample.w[wi*L]),out);
|
||||
len++;
|
||||
out+=nch;
|
||||
// Update wi to point at the correct polyphase component
|
||||
wi=(wi+dn)%up;
|
||||
|
||||
// Insert i number of new samples in queue
|
||||
i = inc;
|
||||
if(wi<level) i++;
|
||||
}
|
||||
}
|
||||
L5:
|
||||
SAVE_QUE(x);
|
||||
}
|
||||
|
||||
// Save values that needs to be kept for next time
|
||||
pwi = wi;
|
||||
pxi = xi;
|
||||
@ -219,8 +273,3 @@ L5:
|
||||
ao_plugin_data.data=pl_resample.data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user