2007-11-06 21:41:16 +00:00
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
2012-09-09 16:57:42 +01:00
Rubber Band Library
2007-11-06 21:41:16 +00:00
An audio time - stretching and pitch - shifting library .
2020-01-16 10:20:23 +00:00
Copyright 2007 - 2020 Particular Programs Ltd .
2012-09-09 16:57:42 +01:00
2007-11-06 21:41:16 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of the
License , or ( at your option ) any later version . See the file
COPYING included with this distribution for more information .
2012-09-09 16:57:42 +01:00
Alternatively , if you have a valid commercial licence for the
Rubber Band Library obtained by agreement with the copyright
holders , you may redistribute and / or modify it under the terms
described in that licence .
If you wish to distribute code using the Rubber Band Library
under terms other than those of the GNU General Public License ,
you must obtain a valid commercial licence before doing so .
2007-11-06 21:41:16 +00:00
*/
# include "Resampler.h"
2009-09-17 13:01:21 +00:00
# include "base/Profiler.h"
2008-05-22 16:54:27 +00:00
2007-11-06 21:41:16 +00:00
# include <cstdlib>
# include <cmath>
# include <iostream>
2015-07-09 15:14:47 +01:00
# include <algorithm>
2007-11-06 21:41:16 +00:00
2009-09-17 13:01:21 +00:00
# include "system/Allocators.h"
2020-10-21 15:05:14 +01:00
# include "system/VectorOps.h"
2009-09-17 13:01:21 +00:00
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
2018-05-14 20:41:25 +01:00
# include <ippversion.h>
# if (IPP_VERSION_MAJOR < 7)
2012-09-09 16:57:42 +01:00
# include <ipps.h>
# include <ippsr.h>
# include <ippac.h>
2018-05-14 20:41:25 +01:00
# else
# include <ipps.h>
# endif
2012-09-09 16:57:42 +01:00
# endif
2007-11-06 21:41:16 +00:00
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBSAMPLERATE
2007-11-06 21:41:16 +00:00
# include <samplerate.h>
2011-01-07 21:46:36 +00:00
# endif
2007-11-06 21:41:16 +00:00
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBRESAMPLE
# include <libresample.h>
# endif
2008-05-22 16:54:27 +00:00
2012-09-09 16:57:42 +01:00
# ifdef USE_SPEEX
# include "speex/speex_resampler.h"
# endif
2008-05-22 16:54:27 +00:00
2012-09-09 16:57:42 +01:00
# ifndef HAVE_IPP
2011-01-07 21:46:36 +00:00
# ifndef HAVE_LIBSAMPLERATE
# ifndef HAVE_LIBRESAMPLE
2012-09-09 16:57:42 +01:00
# ifndef USE_SPEEX
2011-01-07 21:46:36 +00:00
# error No resampler implementation selected!
# endif
# endif
2012-09-09 16:57:42 +01:00
# endif
# endif
2011-01-07 21:46:36 +00:00
2020-10-21 15:05:14 +01:00
using namespace std ;
2007-11-06 21:41:16 +00:00
namespace RubberBand {
2020-10-21 15:05:14 +01:00
class Resampler : : Impl
2008-05-22 16:54:27 +00:00
{
public :
2020-10-21 15:05:14 +01:00
virtual ~ Impl ( ) { }
2008-05-22 16:54:27 +00:00
2020-10-21 15:05:14 +01:00
virtual int resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2008-05-22 16:54:27 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2008-05-22 16:54:27 +00:00
bool final ) = 0 ;
2010-03-24 09:44:51 +00:00
2020-10-21 15:05:14 +01:00
virtual int resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2010-03-24 09:44:51 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2010-03-24 09:44:51 +00:00
bool final ) = 0 ;
2008-05-22 16:54:27 +00:00
2009-09-17 13:01:21 +00:00
virtual int getChannelCount ( ) const = 0 ;
2008-05-22 16:54:27 +00:00
virtual void reset ( ) = 0 ;
} ;
namespace Resamplers {
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
2020-10-21 15:05:14 +01:00
class D_IPP : public Resampler : : Impl
2012-09-09 16:57:42 +01:00
{
public :
2020-10-21 15:05:14 +01:00
D_IPP ( Resampler : : Quality quality , int channels , double initialSampleRate ,
int maxBufferSize , int debugLevel ) ;
2012-09-09 16:57:42 +01:00
~ D_IPP ( ) ;
2020-10-21 15:05:14 +01:00
int resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final ) ;
2020-10-21 15:05:14 +01:00
int resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final = false ) ;
int getChannelCount ( ) const { return m_channels ; }
void reset ( ) ;
protected :
2018-05-14 20:41:25 +01:00
// to m_outbuf
int doResample ( int outcount , double ratio , bool final ) ;
2020-10-21 15:05:14 +01:00
2012-09-09 16:57:42 +01:00
IppsResamplingPolyphase_32f * * m_state ;
2020-10-21 15:05:14 +01:00
double m_initialSampleRate ;
2012-09-09 16:57:42 +01:00
float * * m_inbuf ;
size_t m_inbufsz ;
float * * m_outbuf ;
size_t m_outbufsz ;
int m_bufsize ;
int m_channels ;
int m_window ;
float m_factor ;
int m_history ;
int * m_lastread ;
double * m_time ;
int m_debugLevel ;
void setBufSize ( int ) ;
} ;
2020-10-21 15:05:14 +01:00
D_IPP : : D_IPP ( Resampler : : Quality quality , int channels , double initialSampleRate ,
int maxBufferSize , int debugLevel ) :
2012-09-09 16:57:42 +01:00
m_state ( 0 ) ,
2020-10-21 15:05:14 +01:00
m_initialSampleRate ( initialSampleRate ) ,
2012-09-09 16:57:42 +01:00
m_channels ( channels ) ,
m_debugLevel ( debugLevel )
{
if ( m_debugLevel > 0 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: using IPP implementation "
< < endl ;
2012-09-09 16:57:42 +01:00
}
2018-05-14 20:41:25 +01:00
int nStep = 16 ;
IppHintAlgorithm hint = ippAlgHintFast ;
2012-09-09 16:57:42 +01:00
2020-10-21 15:05:14 +01:00
//!!! todo: make use of initialSampleRate to calculate parameters
2012-09-09 16:57:42 +01:00
switch ( quality ) {
case Resampler : : Best :
m_window = 64 ;
nStep = 80 ;
hint = ippAlgHintAccurate ;
break ;
case Resampler : : FastestTolerable :
nStep = 16 ;
m_window = 16 ;
hint = ippAlgHintFast ;
break ;
case Resampler : : Fastest :
m_window = 24 ;
nStep = 64 ;
hint = ippAlgHintFast ;
break ;
}
m_factor = 8 ; // initial upper bound on m_ratio, may be amended later
2020-10-21 15:05:14 +01:00
// This is largely based on the IPP docs and examples. Adapted
// from the docs:
//
// m_time defines the time value for which the first output
// sample is calculated. The input vector with indices less
// than m_time [whose initial value is m_history below]
// contains the history data of filters.
//
// The history length is [(1/2) window * max(1, 1/factor) ]+1
// where window is the size of the ideal lowpass filter
// window. The input vector must contain the same number of
// elements with indices greater than m_time + length for the
// right filter wing for the last element.
m_history = int ( m_window * 0.5 * max ( 1.0 , 1.0 / m_factor ) ) + 1 ;
2012-09-09 16:57:42 +01:00
m_state = new IppsResamplingPolyphase_32f * [ m_channels ] ;
m_lastread = new int [ m_channels ] ;
m_time = new double [ m_channels ] ;
2018-05-14 20:41:25 +01:00
m_inbufsz = 0 ;
m_outbufsz = 0 ;
m_inbuf = 0 ;
m_outbuf = 0 ;
m_bufsize = 0 ;
2020-10-21 15:05:14 +01:00
2018-05-14 20:41:25 +01:00
setBufSize ( maxBufferSize + m_history ) ;
2012-09-09 16:57:42 +01:00
if ( m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: bufsize = " < < m_bufsize < < " , window = " < < m_window < < " , nStep = " < < nStep < < " , history = " < < m_history < < endl ;
2012-09-09 16:57:42 +01:00
}
2018-05-14 20:41:25 +01:00
# if (IPP_VERSION_MAJOR >= 7)
int specSize = 0 ;
ippsResamplePolyphaseGetSize_32f ( float ( m_window ) ,
nStep ,
& specSize ,
hint ) ;
if ( specSize = = 0 ) {
# ifndef NO_EXCEPTIONS
throw Resampler : : ImplementationError ;
# else
abort ( ) ;
# endif
}
# endif
2012-09-09 16:57:42 +01:00
for ( int c = 0 ; c < m_channels ; + + c ) {
2018-05-14 20:41:25 +01:00
# if (IPP_VERSION_MAJOR < 7)
2012-09-09 16:57:42 +01:00
ippsResamplePolyphaseInitAlloc_32f ( & m_state [ c ] ,
float ( m_window ) ,
nStep ,
0.95f ,
9.0f ,
hint ) ;
2018-05-14 20:41:25 +01:00
# else
m_state [ c ] = ( IppsResamplingPolyphase_32f * ) ippsMalloc_8u ( specSize ) ;
ippsResamplePolyphaseInit_32f ( float ( m_window ) ,
nStep ,
0.95f ,
9.0f ,
m_state [ c ] ,
hint ) ;
2020-10-22 13:55:50 +01:00
if ( m_debugLevel > 1 ) {
cerr < < " D_IPP: Resampler state size = " < < specSize < < " , allocated at "
< < m_state [ c ] < < endl ;
}
2018-05-14 20:41:25 +01:00
# endif
2012-09-09 16:57:42 +01:00
m_lastread [ c ] = m_history ;
m_time [ c ] = m_history ;
}
if ( m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: Resampler init done " < < endl ;
2012-09-09 16:57:42 +01:00
}
}
D_IPP : : ~ D_IPP ( )
{
2018-05-14 20:41:25 +01:00
# if (IPP_VERSION_MAJOR < 7)
2012-09-09 16:57:42 +01:00
for ( int c = 0 ; c < m_channels ; + + c ) {
ippsResamplePolyphaseFree_32f ( m_state [ c ] ) ;
}
2018-05-14 20:41:25 +01:00
# else
for ( int c = 0 ; c < m_channels ; + + c ) {
ippsFree ( m_state [ c ] ) ;
}
# endif
2012-09-09 16:57:42 +01:00
deallocate_channels ( m_inbuf , m_channels ) ;
deallocate_channels ( m_outbuf , m_channels ) ;
delete [ ] m_lastread ;
delete [ ] m_time ;
delete [ ] m_state ;
}
void
D_IPP : : setBufSize ( int sz )
{
if ( m_debugLevel > 1 ) {
2020-10-21 15:05:14 +01:00
if ( m_bufsize > 0 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: resize bufsize " < < m_bufsize < < " -> " ;
2020-10-21 15:05:14 +01:00
} else {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: initialise bufsize to " ;
2020-10-21 15:05:14 +01:00
}
2012-09-09 16:57:42 +01:00
}
m_bufsize = sz ;
2018-05-14 20:41:25 +01:00
if ( m_debugLevel > 1 ) {
2020-10-21 15:05:14 +01:00
cerr < < m_bufsize < < endl ;
2018-05-14 20:41:25 +01:00
}
2012-09-09 16:57:42 +01:00
int n1 = m_bufsize + m_history + 2 ;
if ( m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: inbuf allocating " < < m_bufsize < < " + " < < m_history < < " + 2 = " < < n1 < < endl ;
2020-10-21 15:05:14 +01:00
}
int n2 = ( int ) lrintf ( ceil ( ( m_bufsize - m_history ) * m_factor + 2 ) ) ;
if ( m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: outbuf allocating ( " < < m_bufsize < < " - " < < m_history < < " ) * " < < m_factor < < " + 2 = " < < n2 < < endl ;
2012-09-09 16:57:42 +01:00
}
m_inbuf = reallocate_and_zero_extend_channels
( m_inbuf , m_channels , m_inbufsz , m_channels , n1 ) ;
m_outbuf = reallocate_and_zero_extend_channels
( m_outbuf , m_channels , m_outbufsz , m_channels , n2 ) ;
2020-10-22 13:55:50 +01:00
2012-09-09 16:57:42 +01:00
m_inbufsz = n1 ;
m_outbufsz = n2 ;
2020-10-22 13:55:50 +01:00
if ( m_debugLevel > 2 ) {
cerr < < " D_IPP: inbuf ptr = " < < m_inbuf < < " , channel inbufs " ;
for ( int c = 0 ; c < m_channels ; + + c ) {
cerr < < m_inbuf [ c ] < < " " ;
}
cerr < < " at " < < m_inbufsz * sizeof ( float ) < < " bytes each " < < endl ;
cerr < < " D_IPP: outbuf ptr = " < < m_outbuf < < " , channel outbufs " ;
for ( int c = 0 ; c < m_channels ; + + c ) {
cerr < < m_outbuf [ c ] < < " " ;
}
cerr < < " at " < < m_outbufsz * sizeof ( float ) < < " bytes each " < < endl ;
}
2012-09-09 16:57:42 +01:00
}
int
2020-10-21 15:05:14 +01:00
D_IPP : : resample ( float * const R__ * const R__ out ,
int outspace ,
const float * const R__ * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final )
{
if ( ratio > m_factor ) {
m_factor = ratio ;
2020-10-21 15:05:14 +01:00
m_history = int ( m_window * 0.5 * max ( 1.0 , 1.0 / m_factor ) ) + 1 ;
}
if ( m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: incount = " < < incount < < " , ratio = " < < ratio < < " , est space = " < < lrintf ( ceil ( incount * ratio ) ) < < " , outspace = " < < outspace < < " , final = " < < final < < endl ;
2012-09-09 16:57:42 +01:00
}
for ( int c = 0 ; c < m_channels ; + + c ) {
if ( m_lastread [ c ] + incount + m_history > m_bufsize ) {
setBufSize ( m_lastread [ c ] + incount + m_history ) ;
}
}
for ( int c = 0 ; c < m_channels ; + + c ) {
for ( int i = 0 ; i < incount ; + + i ) {
m_inbuf [ c ] [ m_lastread [ c ] + i ] = in [ c ] [ i ] ;
}
m_lastread [ c ] + = incount ;
}
2020-10-21 15:05:14 +01:00
if ( m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: lastread advanced to " < < m_lastread [ 0 ] < < endl ;
2020-10-21 15:05:14 +01:00
}
int got = doResample ( outspace , ratio , final ) ;
2012-09-09 16:57:42 +01:00
for ( int c = 0 ; c < m_channels ; + + c ) {
2018-05-14 20:41:25 +01:00
v_copy ( out [ c ] , m_outbuf [ c ] , got ) ;
2012-09-09 16:57:42 +01:00
}
2018-05-14 20:41:25 +01:00
return got ;
2012-09-09 16:57:42 +01:00
}
int
2020-10-21 15:05:14 +01:00
D_IPP : : resampleInterleaved ( float * const R__ out ,
int outspace ,
const float * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final )
{
if ( ratio > m_factor ) {
m_factor = ratio ;
2020-10-21 15:05:14 +01:00
m_history = int ( m_window * 0.5 * max ( 1.0 , 1.0 / m_factor ) ) + 1 ;
}
if ( m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: incount = " < < incount < < " , ratio = " < < ratio < < " , est space = " < < lrintf ( ceil ( incount * ratio ) ) < < " , outspace = " < < outspace < < " , final = " < < final < < endl ;
2012-09-09 16:57:42 +01:00
}
for ( int c = 0 ; c < m_channels ; + + c ) {
if ( m_lastread [ c ] + incount + m_history > m_bufsize ) {
setBufSize ( m_lastread [ c ] + incount + m_history ) ;
}
}
for ( int c = 0 ; c < m_channels ; + + c ) {
for ( int i = 0 ; i < incount ; + + i ) {
m_inbuf [ c ] [ m_lastread [ c ] + i ] = in [ i * m_channels + c ] ;
}
m_lastread [ c ] + = incount ;
2018-05-14 20:41:25 +01:00
}
2020-10-21 15:05:14 +01:00
if ( m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: lastread advanced to " < < m_lastread [ 0 ] < < " after injection of "
2020-10-21 15:05:14 +01:00
< < incount < < " samples " < < endl ;
}
int got = doResample ( outspace , ratio , final ) ;
2018-05-14 20:41:25 +01:00
v_interleave ( out , m_outbuf , m_channels , got ) ;
return got ;
}
int
D_IPP : : doResample ( int outspace , double ratio , bool final )
{
int outcount = 0 ;
for ( int c = 0 ; c < m_channels ; + + c ) {
int n = m_lastread [ c ] - m_history - int ( m_time [ c ] ) ;
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: at start, lastread = " < < m_lastread [ c ] < < " , history = "
2018-05-14 20:41:25 +01:00
< < m_history < < " , time = " < < m_time [ c ] < < " , therefore n = "
2020-10-21 15:05:14 +01:00
< < n < < endl ;
2018-05-14 20:41:25 +01:00
}
if ( n < = 0 ) {
if ( c = = 0 & & m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: not enough input samples to do anything " < < endl ;
2018-05-14 20:41:25 +01:00
}
continue ;
}
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: before resample call, time = " < < m_time [ c ] < < endl ;
2018-05-14 20:41:25 +01:00
}
// We're committed to not overrunning outspace, so we need to
// offer the resampler only enough samples to ensure it won't
int limit = int ( floor ( outspace / ratio ) ) ;
if ( n > limit ) {
if ( c = = 0 & & m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: trimming input samples from " < < n < < " to " < < limit
2018-05-14 20:41:25 +01:00
< < " to avoid overrunning " < < outspace < < " at output "
2020-10-21 15:05:14 +01:00
< < endl ;
2018-05-14 20:41:25 +01:00
}
n = limit ;
}
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
# if (IPP_VERSION_MAJOR < 7)
2012-09-09 16:57:42 +01:00
ippsResamplePolyphase_32f ( m_state [ c ] ,
m_inbuf [ c ] ,
2018-05-14 20:41:25 +01:00
n ,
2012-09-09 16:57:42 +01:00
m_outbuf [ c ] ,
ratio ,
2018-05-14 20:41:25 +01:00
1.0f ,
2012-09-09 16:57:42 +01:00
& m_time [ c ] ,
& outcount ) ;
2018-05-14 20:41:25 +01:00
# else
ippsResamplePolyphase_32f ( m_inbuf [ c ] ,
n ,
m_outbuf [ c ] ,
ratio ,
1.0f ,
& m_time [ c ] ,
& outcount ,
m_state [ c ] ) ;
# endif
2012-09-09 16:57:42 +01:00
2020-10-22 13:55:50 +01:00
int t = int ( floor ( m_time [ c ] ) ) ;
int moveFrom = t - m_history ;
2018-05-14 20:41:25 +01:00
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: converted " < < n < < " samples to " < < outcount
< < " (nb outbufsz = " < < m_outbufsz
< < " ), time advanced to " < < m_time [ c ] < < endl ;
cerr < < " D_IPP: rounding time to " < < t < < " , lastread = "
< < m_lastread [ c ] < < " , history = " < < m_history < < endl ;
cerr < < " D_IPP: will move " < < m_lastread [ c ] - moveFrom
< < " unconverted samples back from index " < < moveFrom
2020-10-21 15:05:14 +01:00
< < " to 0 " < < endl ;
2018-05-14 20:41:25 +01:00
}
2020-10-22 13:55:50 +01:00
if ( moveFrom > = m_lastread [ c ] ) {
moveFrom = m_lastread [ c ] ;
2012-09-09 16:57:42 +01:00
2020-10-22 13:55:50 +01:00
if ( c = = 0 & & m_debugLevel > 2 ) {
cerr < < " D_IPP: number of samples to move is <= 0, "
< < " not actually moving any " < < endl ;
}
} else {
v_move ( m_inbuf [ c ] ,
m_inbuf [ c ] + moveFrom ,
m_lastread [ c ] - moveFrom ) ;
}
2012-09-09 16:57:42 +01:00
2020-10-22 13:55:50 +01:00
m_lastread [ c ] - = moveFrom ;
m_time [ c ] - = moveFrom ;
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: lastread reduced to " < < m_lastread [ c ]
2018-05-14 20:41:25 +01:00
< < " , time reduced to " < < m_time [ c ]
2020-10-21 15:05:14 +01:00
< < endl ;
2018-05-14 20:41:25 +01:00
}
if ( final & & n < limit ) {
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
// Looks like this actually produces too many samples
// (additionalcount is a few samples too large).
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
// Also, we aren't likely to have enough space in the
// output buffer as the caller won't have allowed for
// all the samples we're retrieving here.
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
// What to do?
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
int additionalcount = 0 ;
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: final call, padding input with " < < m_history
2020-10-21 15:05:14 +01:00
< < " zeros (symmetrical with m_history) " < < endl ;
2018-05-14 20:41:25 +01:00
}
2012-09-09 16:57:42 +01:00
for ( int i = 0 ; i < m_history ; + + i ) {
m_inbuf [ c ] [ m_lastread [ c ] + i ] = 0.f ;
}
2018-05-14 20:41:25 +01:00
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: before resample call, time = " < < m_time [ c ] < < endl ;
2018-05-14 20:41:25 +01:00
}
int nAdditional = m_lastread [ c ] - int ( m_time [ c ] ) ;
if ( n + nAdditional > limit ) {
if ( c = = 0 & & m_debugLevel > 1 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: trimming final input samples from " < < nAdditional
2018-05-14 20:41:25 +01:00
< < " to " < < ( limit - n )
< < " to avoid overrunning " < < outspace < < " at output "
2020-10-21 15:05:14 +01:00
< < endl ;
2018-05-14 20:41:25 +01:00
}
nAdditional = limit - n ;
}
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
# if (IPP_VERSION_MAJOR < 7)
2012-09-09 16:57:42 +01:00
ippsResamplePolyphase_32f ( m_state [ c ] ,
m_inbuf [ c ] ,
2018-05-14 20:41:25 +01:00
nAdditional ,
2012-09-09 16:57:42 +01:00
m_outbuf [ c ] ,
ratio ,
2018-05-14 20:41:25 +01:00
1.0f ,
2012-09-09 16:57:42 +01:00
& m_time [ c ] ,
& additionalcount ) ;
2018-05-14 20:41:25 +01:00
# else
ippsResamplePolyphase_32f ( m_inbuf [ c ] ,
nAdditional ,
m_outbuf [ c ] ,
ratio ,
1.0f ,
& m_time [ c ] ,
& additionalcount ,
m_state [ c ] ) ;
# endif
if ( c = = 0 & & m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: converted " < < n < < " samples to " < < additionalcount
2020-10-21 15:05:14 +01:00
< < " , time advanced to " < < m_time [ c ] < < endl ;
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: outcount = " < < outcount < < " , additionalcount = " < < additionalcount < < " , sum " < < outcount + additionalcount < < endl ;
2018-05-14 20:41:25 +01:00
}
2012-09-09 16:57:42 +01:00
2018-05-14 20:41:25 +01:00
if ( c = = 0 ) {
outcount + = additionalcount ;
2012-09-09 16:57:42 +01:00
}
}
}
2018-05-14 20:41:25 +01:00
if ( m_debugLevel > 2 ) {
2020-10-22 13:55:50 +01:00
cerr < < " D_IPP: returning " < < outcount < < " samples " < < endl ;
2018-05-14 20:41:25 +01:00
}
2012-09-09 16:57:42 +01:00
return outcount ;
}
void
D_IPP : : reset ( )
{
//!!!
}
# endif /* HAVE_IPP */
2008-05-22 16:54:27 +00:00
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBSAMPLERATE
2008-05-22 16:54:27 +00:00
2020-10-21 15:05:14 +01:00
class D_SRC : public Resampler : : Impl
2007-11-06 21:41:16 +00:00
{
public :
2020-10-21 15:05:14 +01:00
D_SRC ( Resampler : : Quality quality , int channels , double initialSampleRate ,
int maxBufferSize , int m_debugLevel ) ;
2008-05-22 16:54:27 +00:00
~ D_SRC ( ) ;
2007-11-06 21:41:16 +00:00
2020-10-21 15:05:14 +01:00
int resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2008-05-22 16:54:27 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2008-05-22 16:54:27 +00:00
bool final ) ;
2007-11-06 21:41:16 +00:00
2020-10-21 15:05:14 +01:00
int resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2010-03-24 09:44:51 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2010-03-24 09:44:51 +00:00
bool final = false ) ;
2009-09-17 13:01:21 +00:00
int getChannelCount ( ) const { return m_channels ; }
2007-11-06 21:41:16 +00:00
void reset ( ) ;
protected :
SRC_STATE * m_src ;
float * m_iin ;
float * m_iout ;
2008-05-22 16:54:27 +00:00
int m_channels ;
int m_iinsize ;
int m_ioutsize ;
2020-10-21 17:16:15 +01:00
double m_prevRatio ;
2008-05-22 16:54:27 +00:00
int m_debugLevel ;
2007-11-06 21:41:16 +00:00
} ;
2020-10-21 15:05:14 +01:00
D_SRC : : D_SRC ( Resampler : : Quality quality , int channels , double ,
int maxBufferSize , int debugLevel ) :
2007-11-06 21:41:16 +00:00
m_src ( 0 ) ,
m_iin ( 0 ) ,
m_iout ( 0 ) ,
m_channels ( channels ) ,
m_iinsize ( 0 ) ,
2008-05-22 16:54:27 +00:00
m_ioutsize ( 0 ) ,
2020-10-21 17:16:15 +01:00
m_prevRatio ( 1.0 ) ,
2008-05-22 16:54:27 +00:00
m_debugLevel ( debugLevel )
2007-11-06 21:41:16 +00:00
{
2008-05-22 16:54:27 +00:00
if ( m_debugLevel > 0 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: using libsamplerate implementation "
< < endl ;
2008-05-22 16:54:27 +00:00
}
2007-11-06 21:41:16 +00:00
int err = 0 ;
2008-05-22 16:54:27 +00:00
m_src = src_new ( quality = = Resampler : : Best ? SRC_SINC_BEST_QUALITY :
quality = = Resampler : : Fastest ? SRC_LINEAR :
2007-11-06 21:41:16 +00:00
SRC_SINC_FASTEST ,
channels , & err ) ;
2008-07-01 14:54:31 +00:00
if ( err ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: failed to create libsamplerate resampler: "
< < src_strerror ( err ) < < endl ;
2012-09-09 16:57:42 +01:00
# ifndef NO_EXCEPTIONS
2011-11-25 11:11:59 +00:00
throw Resampler : : ImplementationError ;
2012-09-09 16:57:42 +01:00
# endif
2008-07-01 14:54:31 +00:00
}
2007-11-06 21:41:16 +00:00
if ( maxBufferSize > 0 & & m_channels > 1 ) {
m_iinsize = maxBufferSize * m_channels ;
m_ioutsize = maxBufferSize * m_channels * 2 ;
2009-09-17 13:01:21 +00:00
m_iin = allocate < float > ( m_iinsize ) ;
m_iout = allocate < float > ( m_ioutsize ) ;
2007-11-06 21:41:16 +00:00
}
2008-07-04 14:19:32 +00:00
reset ( ) ;
2007-11-06 21:41:16 +00:00
}
2008-05-22 16:54:27 +00:00
D_SRC : : ~ D_SRC ( )
2007-11-06 21:41:16 +00:00
{
src_delete ( m_src ) ;
2011-01-07 21:46:36 +00:00
deallocate ( m_iin ) ;
deallocate ( m_iout ) ;
2007-11-06 21:41:16 +00:00
}
2008-05-22 16:54:27 +00:00
int
2020-10-21 15:05:14 +01:00
D_SRC : : resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2008-05-22 16:54:27 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2008-05-22 16:54:27 +00:00
bool final )
2007-11-06 21:41:16 +00:00
{
if ( m_channels = = 1 ) {
2020-10-21 15:05:14 +01:00
return resampleInterleaved ( * out , outcount , * in , incount , ratio , final ) ;
2007-11-06 21:41:16 +00:00
}
2020-10-21 15:05:14 +01:00
if ( incount * m_channels > m_iinsize ) {
m_iin = reallocate < float > ( m_iin , m_iinsize , incount * m_channels ) ;
m_iinsize = incount * m_channels ;
2020-09-15 13:46:18 +01:00
}
2020-10-21 15:05:14 +01:00
if ( outcount * m_channels > m_ioutsize ) {
m_iout = reallocate < float > ( m_iout , m_ioutsize , outcount * m_channels ) ;
m_ioutsize = outcount * m_channels ;
2008-07-01 14:54:31 +00:00
}
2020-10-21 15:05:14 +01:00
v_interleave ( m_iin , in , m_channels , incount ) ;
2007-11-06 21:41:16 +00:00
2020-10-21 15:05:14 +01:00
int n = resampleInterleaved ( m_iout , outcount , m_iin , incount , ratio , final ) ;
2020-09-15 13:46:18 +01:00
2020-10-21 15:05:14 +01:00
v_deinterleave ( out , m_iout , m_channels , n ) ;
2020-09-15 13:46:18 +01:00
2020-10-21 15:05:14 +01:00
return n ;
2010-03-24 09:44:51 +00:00
}
int
2020-10-21 15:05:14 +01:00
D_SRC : : resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2010-03-24 09:44:51 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2010-03-24 09:44:51 +00:00
bool final )
{
SRC_DATA data ;
2020-10-21 17:16:15 +01:00
// libsamplerate smooths the filter change over the duration of
// the processing block to avoid artifacts due to sudden changes,
// and it uses outcount to determine how long to smooth the change
// over. This is a good thing, but it does mean (a) we should
// never pass outcount significantly longer than the actual
// expected output, and (b) when the ratio has just changed, we
// should aim to supply a shortish block next
if ( outcount > int ( ceil ( incount * ratio ) + 5 ) ) {
outcount = int ( ceil ( incount * ratio ) + 5 ) ;
}
if ( ratio ! = m_prevRatio ) {
// If we are processing a block of appreciable length, turn it
// into two recursive calls, one for the short smoothing block
// and the other for the rest. Update m_prevRatio before doing
// this so that the calls don't themselves recurse!
m_prevRatio = ratio ;
int shortBlock = 200 ;
if ( outcount > shortBlock * 2 ) {
int shortIn = int ( floor ( shortBlock / ratio ) ) ;
if ( shortIn > = 10 ) {
int shortOut =
resampleInterleaved ( out , shortBlock ,
in , shortIn ,
ratio , false ) ;
int remainingOut = 0 ;
if ( shortOut < outcount ) {
remainingOut =
resampleInterleaved ( out + shortOut * m_channels ,
outcount - shortOut ,
in + shortIn * m_channels ,
incount - shortIn ,
ratio , final ) ;
}
return shortOut + remainingOut ;
}
}
}
2010-03-24 09:44:51 +00:00
data . data_in = const_cast < float * > ( in ) ;
data . data_out = out ;
data . input_frames = incount ;
data . output_frames = outcount ;
2020-10-21 16:50:19 +01:00
2010-03-24 09:44:51 +00:00
data . src_ratio = ratio ;
data . end_of_input = ( final ? 1 : 0 ) ;
2020-10-21 16:50:19 +01:00
2010-03-24 09:44:51 +00:00
int err = src_process ( m_src , & data ) ;
if ( err ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::process: libsamplerate error: "
< < src_strerror ( err ) < < endl ;
2012-09-09 16:57:42 +01:00
# ifndef NO_EXCEPTIONS
2011-11-25 11:11:59 +00:00
throw Resampler : : ImplementationError ;
2012-09-09 16:57:42 +01:00
# endif
2007-11-06 21:41:16 +00:00
}
2020-10-21 16:50:19 +01:00
2020-10-21 15:05:14 +01:00
return ( int ) data . output_frames_gen ;
2007-11-06 21:41:16 +00:00
}
void
2008-05-22 16:54:27 +00:00
D_SRC : : reset ( )
2007-11-06 21:41:16 +00:00
{
src_reset ( m_src ) ;
}
2011-01-07 21:46:36 +00:00
# endif /* HAVE_LIBSAMPLERATE */
# ifdef HAVE_LIBRESAMPLE
2020-10-21 15:05:14 +01:00
class D_Resample : public Resampler : : Impl
2011-01-07 21:46:36 +00:00
{
public :
2020-10-21 15:05:14 +01:00
D_Resample ( Resampler : : Quality quality , int channels , double initialSampleRate ,
int maxBufferSize , int m_debugLevel ) ;
2011-01-07 21:46:36 +00:00
~ D_Resample ( ) ;
2020-10-21 15:05:14 +01:00
int resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2011-01-07 21:46:36 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2011-01-07 21:46:36 +00:00
bool final ) ;
2020-10-21 15:05:14 +01:00
int resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2011-01-07 21:46:36 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2011-01-07 21:46:36 +00:00
bool final ) ;
int getChannelCount ( ) const { return m_channels ; }
void reset ( ) ;
protected :
void * m_src ;
float * m_iin ;
float * m_iout ;
2020-10-21 15:05:14 +01:00
double m_lastRatio ;
2011-01-07 21:46:36 +00:00
int m_channels ;
int m_iinsize ;
int m_ioutsize ;
int m_debugLevel ;
} ;
2020-10-21 15:05:14 +01:00
D_Resample : : D_Resample ( Resampler : : Quality quality ,
int channels , double , int maxBufferSize , int debugLevel ) :
2011-01-07 21:46:36 +00:00
m_src ( 0 ) ,
m_iin ( 0 ) ,
m_iout ( 0 ) ,
m_channels ( channels ) ,
m_iinsize ( 0 ) ,
m_ioutsize ( 0 ) ,
m_debugLevel ( debugLevel )
{
if ( m_debugLevel > 0 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: using libresample implementation "
< < endl ;
2011-01-07 21:46:36 +00:00
}
float min_factor = 0.125f ;
float max_factor = 8.0f ;
m_src = resample_open ( quality = = Resampler : : Best ? 1 : 0 , min_factor , max_factor ) ;
if ( ! m_src ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: failed to create libresample resampler: "
< < endl ;
2011-01-07 21:46:36 +00:00
throw Resampler : : ImplementationError ; //!!! of course, need to catch this!
}
if ( maxBufferSize > 0 & & m_channels > 1 ) {
m_iinsize = maxBufferSize * m_channels ;
m_ioutsize = maxBufferSize * m_channels * 2 ;
m_iin = allocate < float > ( m_iinsize ) ;
m_iout = allocate < float > ( m_ioutsize ) ;
}
reset ( ) ;
}
D_Resample : : ~ D_Resample ( )
{
resample_close ( m_src ) ;
if ( m_iinsize > 0 ) {
deallocate ( m_iin ) ;
}
if ( m_ioutsize > 0 ) {
deallocate ( m_iout ) ;
}
}
int
2020-10-21 15:05:14 +01:00
D_Resample : : resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2011-01-07 21:46:36 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2011-01-07 21:46:36 +00:00
bool final )
{
float * data_in ;
float * data_out ;
int input_frames , output_frames , end_of_input , source_used ;
float src_ratio ;
2020-10-21 15:05:14 +01:00
int outcount = ( int ) lrint ( ceil ( incount * ratio ) ) ;
2011-01-07 21:46:36 +00:00
if ( m_channels = = 1 ) {
data_in = const_cast < float * > ( * in ) ; //!!!???
data_out = * out ;
} else {
if ( incount * m_channels > m_iinsize ) {
m_iin = reallocate < float > ( m_iin , m_iinsize , incount * m_channels ) ;
m_iinsize = incount * m_channels ;
}
if ( outcount * m_channels > m_ioutsize ) {
m_iout = reallocate < float > ( m_iout , m_ioutsize , outcount * m_channels ) ;
m_ioutsize = outcount * m_channels ;
}
v_interleave ( m_iin , in , m_channels , incount ) ;
data_in = m_iin ;
data_out = m_iout ;
}
input_frames = incount ;
output_frames = outcount ;
src_ratio = ratio ;
end_of_input = ( final ? 1 : 0 ) ;
int output_frames_gen = resample_process ( m_src ,
src_ratio ,
data_in ,
input_frames ,
end_of_input ,
& source_used ,
data_out ,
output_frames ) ;
if ( output_frames_gen < 0 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::process: libresample error: "
< < endl ;
2011-01-07 21:46:36 +00:00
throw Resampler : : ImplementationError ; //!!! of course, need to catch this!
}
if ( m_channels > 1 ) {
v_deinterleave ( out , m_iout , m_channels , output_frames_gen ) ;
}
return output_frames_gen ;
}
int
2020-10-21 15:05:14 +01:00
D_Resample : : resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2011-01-07 21:46:36 +00:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2011-01-07 21:46:36 +00:00
bool final )
{
int input_frames , output_frames , end_of_input , source_used ;
float src_ratio ;
2020-10-21 15:05:14 +01:00
int outcount = ( int ) lrint ( ceil ( incount * ratio ) ) ;
2011-01-07 21:46:36 +00:00
input_frames = incount ;
output_frames = outcount ;
src_ratio = ratio ;
end_of_input = ( final ? 1 : 0 ) ;
int output_frames_gen = resample_process ( m_src ,
src_ratio ,
const_cast < float * > ( in ) ,
input_frames ,
end_of_input ,
& source_used ,
out ,
output_frames ) ;
if ( output_frames_gen < 0 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::process: libresample error: "
< < endl ;
2011-01-07 21:46:36 +00:00
throw Resampler : : ImplementationError ; //!!! of course, need to catch this!
}
return output_frames_gen ;
}
void
D_Resample : : reset ( )
{
}
# endif /* HAVE_LIBRESAMPLE */
2007-11-06 21:41:16 +00:00
2012-09-09 16:57:42 +01:00
# ifdef USE_SPEEX
2020-10-21 15:05:14 +01:00
class D_Speex : public Resampler : : Impl
2012-09-09 16:57:42 +01:00
{
public :
2020-10-21 15:05:14 +01:00
D_Speex ( Resampler : : Quality quality , int channels , double initialSampleRate ,
int maxBufferSize , int debugLevel ) ;
2012-09-09 16:57:42 +01:00
~ D_Speex ( ) ;
2020-10-21 15:05:14 +01:00
int resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final ) ;
2020-10-21 15:05:14 +01:00
int resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final = false ) ;
int getChannelCount ( ) const { return m_channels ; }
void reset ( ) ;
protected :
SpeexResamplerState * m_resampler ;
2020-10-21 15:05:14 +01:00
double m_initialSampleRate ;
2012-09-09 16:57:42 +01:00
float * m_iin ;
float * m_iout ;
int m_channels ;
int m_iinsize ;
int m_ioutsize ;
2020-10-21 15:05:14 +01:00
double m_lastratio ;
2012-09-09 16:57:42 +01:00
bool m_initial ;
int m_debugLevel ;
2020-10-21 15:05:14 +01:00
void setRatio ( double ) ;
void doResample ( const float * in , unsigned int & incount ,
float * out , unsigned int & outcount ,
double ratio , bool final ) ;
2012-09-09 16:57:42 +01:00
} ;
2020-10-21 15:05:14 +01:00
D_Speex : : D_Speex ( Resampler : : Quality quality ,
int channels , double initialSampleRate ,
int maxBufferSize , int debugLevel ) :
2012-09-09 16:57:42 +01:00
m_resampler ( 0 ) ,
2020-10-21 15:05:14 +01:00
m_initialSampleRate ( initialSampleRate ) ,
2012-09-09 16:57:42 +01:00
m_iin ( 0 ) ,
m_iout ( 0 ) ,
m_channels ( channels ) ,
m_iinsize ( 0 ) ,
m_ioutsize ( 0 ) ,
2020-10-21 15:05:14 +01:00
m_lastratio ( - 1.0 ) ,
2012-09-09 16:57:42 +01:00
m_initial ( true ) ,
m_debugLevel ( debugLevel )
{
int q = ( quality = = Resampler : : Best ? 10 :
quality = = Resampler : : Fastest ? 0 : 4 ) ;
if ( m_debugLevel > 0 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: using Speex implementation with q = "
< < q < < endl ;
2012-09-09 16:57:42 +01:00
}
2020-10-21 15:05:14 +01:00
int rrate = int ( round ( m_initialSampleRate ) ) ;
2020-09-15 13:46:18 +01:00
2012-09-09 16:57:42 +01:00
int err = 0 ;
m_resampler = speex_resampler_init_frac ( m_channels ,
1 , 1 ,
2020-10-21 15:05:14 +01:00
rrate , rrate ,
2012-09-09 16:57:42 +01:00
q ,
& err ) ;
if ( err ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: failed to create Speex resampler "
< < endl ;
2012-09-09 16:57:42 +01:00
# ifndef NO_EXCEPTIONS
throw Resampler : : ImplementationError ;
# endif
}
if ( maxBufferSize > 0 & & m_channels > 1 ) {
m_iinsize = maxBufferSize * m_channels ;
m_ioutsize = maxBufferSize * m_channels * 2 ;
m_iin = allocate < float > ( m_iinsize ) ;
m_iout = allocate < float > ( m_ioutsize ) ;
}
}
D_Speex : : ~ D_Speex ( )
{
speex_resampler_destroy ( m_resampler ) ;
deallocate < float > ( m_iin ) ;
deallocate < float > ( m_iout ) ;
}
void
2020-10-21 15:05:14 +01:00
D_Speex : : setRatio ( double ratio )
2012-09-09 16:57:42 +01:00
{
// Speex wants a ratio of two unsigned integers, not a single
// float. Let's do that.
unsigned int big = 272408136U ;
unsigned int denom = 1 , num = 1 ;
if ( ratio < 1.f ) {
denom = big ;
double dnum = double ( big ) * double ( ratio ) ;
num = ( unsigned int ) dnum ;
} else if ( ratio > 1.f ) {
num = big ;
double ddenom = double ( big ) / double ( ratio ) ;
denom = ( unsigned int ) ddenom ;
}
if ( m_debugLevel > 1 ) {
2020-10-21 15:05:14 +01:00
cerr < < " D_Speex: Desired ratio " < < ratio < < " , requesting ratio "
< < num < < " / " < < denom < < " = " < < float ( double ( num ) / double ( denom ) )
< < endl ;
2012-09-09 16:57:42 +01:00
}
2020-10-21 15:05:14 +01:00
int fromRate = int ( round ( m_initialSampleRate ) ) ;
int toRate = int ( round ( m_initialSampleRate * ratio ) ) ;
2012-09-09 16:57:42 +01:00
int err = speex_resampler_set_rate_frac
2020-10-21 15:05:14 +01:00
( m_resampler , denom , num , fromRate , toRate ) ;
if ( err ) {
cerr < < " Resampler::Resampler: failed to set rate on Speex resampler "
< < endl ;
# ifndef NO_EXCEPTIONS
throw Resampler : : ImplementationError ;
# endif
}
2012-09-09 16:57:42 +01:00
speex_resampler_get_ratio ( m_resampler , & denom , & num ) ;
if ( m_debugLevel > 1 ) {
2020-10-21 15:05:14 +01:00
cerr < < " D_Speex: Desired ratio " < < ratio < < " , got ratio "
< < num < < " / " < < denom < < " = " < < float ( double ( num ) / double ( denom ) )
< < endl ;
2012-09-09 16:57:42 +01:00
}
m_lastratio = ratio ;
if ( m_initial ) {
speex_resampler_skip_zeros ( m_resampler ) ;
m_initial = false ;
}
}
int
2020-10-21 15:05:14 +01:00
D_Speex : : resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final )
{
if ( ratio ! = m_lastratio ) {
setRatio ( ratio ) ;
}
unsigned int uincount = incount ;
2020-10-21 15:05:14 +01:00
unsigned int uoutcount = outcount ;
2012-09-09 16:57:42 +01:00
float * data_in , * data_out ;
if ( m_channels = = 1 ) {
data_in = const_cast < float * > ( * in ) ;
data_out = * out ;
} else {
2020-10-21 15:05:14 +01:00
if ( int ( incount * m_channels ) > m_iinsize ) {
2012-09-09 16:57:42 +01:00
m_iin = reallocate < float > ( m_iin , m_iinsize , incount * m_channels ) ;
m_iinsize = incount * m_channels ;
}
2020-10-21 15:05:14 +01:00
if ( int ( outcount * m_channels ) > m_ioutsize ) {
2012-09-09 16:57:42 +01:00
m_iout = reallocate < float > ( m_iout , m_ioutsize , outcount * m_channels ) ;
m_ioutsize = outcount * m_channels ;
}
v_interleave ( m_iin , in , m_channels , incount ) ;
data_in = m_iin ;
data_out = m_iout ;
}
2020-10-21 15:05:14 +01:00
doResample ( data_in , uincount , data_out , uoutcount , ratio , final ) ;
2013-05-15 10:35:30 +01:00
2012-09-09 16:57:42 +01:00
if ( m_channels > 1 ) {
2020-10-21 15:05:14 +01:00
v_deinterleave ( out , m_iout , m_channels , uoutcount ) ;
2012-09-09 16:57:42 +01:00
}
2020-10-21 15:05:14 +01:00
return uoutcount ;
2012-09-09 16:57:42 +01:00
}
int
2020-10-21 15:05:14 +01:00
D_Speex : : resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
2012-09-09 16:57:42 +01:00
int incount ,
2020-10-21 15:05:14 +01:00
double ratio ,
2012-09-09 16:57:42 +01:00
bool final )
{
if ( ratio ! = m_lastratio ) {
setRatio ( ratio ) ;
}
unsigned int uincount = incount ;
2020-10-21 15:05:14 +01:00
unsigned int uoutcount = outcount ;
2012-09-09 16:57:42 +01:00
float * data_in = const_cast < float * > ( in ) ;
float * data_out = out ;
2020-10-21 15:05:14 +01:00
doResample ( data_in , uincount , data_out , uoutcount , ratio , final ) ;
return uoutcount ;
}
2012-09-09 16:57:42 +01:00
2020-10-21 15:05:14 +01:00
void
D_Speex : : doResample ( const float * data_in , unsigned int & uincount ,
float * data_out , unsigned int & uoutcount ,
double ratio , bool final )
{
int initial_outcount = int ( uoutcount ) ;
int err = speex_resampler_process_interleaved_float
( m_resampler ,
data_in , & uincount ,
data_out , & uoutcount ) ;
if ( err ) {
cerr < < " Resampler::Resampler: Speex resampler returned error "
< < err < < endl ;
# ifndef NO_EXCEPTIONS
throw Resampler : : ImplementationError ;
# endif
}
2013-05-15 10:35:30 +01:00
2020-10-21 15:05:14 +01:00
if ( final ) {
int actual = int ( uoutcount ) ;
int expected = std : : min ( initial_outcount , int ( round ( uincount * ratio ) ) ) ;
if ( actual < expected ) {
unsigned int final_out = expected - actual ;
unsigned int final_in = ( unsigned int ) ( round ( final_out / ratio ) ) ;
if ( final_in > 0 ) {
float * pad = allocate_and_zero < float > ( final_in * m_channels ) ;
err = speex_resampler_process_interleaved_float
( m_resampler ,
pad , & final_in ,
data_out + actual * m_channels , & final_out ) ;
deallocate ( pad ) ;
uoutcount + = final_out ;
if ( err ) {
cerr < < " Resampler::Resampler: Speex resampler returned error "
< < err < < endl ;
# ifndef NO_EXCEPTIONS
throw Resampler : : ImplementationError ;
# endif
}
}
}
}
2012-09-09 16:57:42 +01:00
}
void
D_Speex : : reset ( )
{
2017-09-26 09:51:22 +01:00
m_lastratio = - 1.0 ; // force reset of ratio
m_initial = true ;
2012-09-09 16:57:42 +01:00
speex_resampler_reset_mem ( m_resampler ) ;
}
# endif
2007-11-06 21:41:16 +00:00
2008-05-22 16:54:27 +00:00
} /* end namespace Resamplers */
2007-11-06 21:41:16 +00:00
2020-10-21 15:05:14 +01:00
Resampler : : Resampler ( Resampler : : Parameters params , int channels )
2007-11-06 21:41:16 +00:00
{
2008-05-22 16:54:27 +00:00
m_method = - 1 ;
2020-10-21 15:05:14 +01:00
if ( params . initialSampleRate = = 0 ) {
params . initialSampleRate = 44100 ;
}
2008-05-22 16:54:27 +00:00
2020-10-21 15:05:14 +01:00
switch ( params . quality ) {
2008-05-22 16:54:27 +00:00
case Resampler : : Best :
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
m_method = 0 ;
# endif
# ifdef USE_SPEEX
m_method = 2 ;
# endif
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBRESAMPLE
m_method = 3 ;
# endif
# ifdef HAVE_LIBSAMPLERATE
2008-05-22 16:54:27 +00:00
m_method = 1 ;
2011-01-07 21:46:36 +00:00
# endif
2008-05-22 16:54:27 +00:00
break ;
case Resampler : : FastestTolerable :
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
m_method = 0 ;
# endif
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBRESAMPLE
m_method = 3 ;
# endif
2012-09-09 16:57:42 +01:00
# ifdef USE_SPEEX
m_method = 2 ;
2020-09-29 11:04:18 +01:00
# endif
# ifdef HAVE_LIBSAMPLERATE
m_method = 1 ;
2011-01-07 21:46:36 +00:00
# endif
2008-05-22 16:54:27 +00:00
break ;
case Resampler : : Fastest :
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
m_method = 0 ;
# endif
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBRESAMPLE
m_method = 3 ;
# endif
2012-09-09 16:57:42 +01:00
# ifdef USE_SPEEX
m_method = 2 ;
# endif
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBSAMPLERATE
2008-05-22 16:54:27 +00:00
m_method = 1 ;
2011-01-07 21:46:36 +00:00
# endif
2008-05-22 16:54:27 +00:00
break ;
}
if ( m_method = = - 1 ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: No implementation available! " < < endl ;
2008-05-22 16:54:27 +00:00
abort ( ) ;
}
switch ( m_method ) {
case 0 :
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
2020-10-21 15:05:14 +01:00
d = new Resamplers : : D_IPP
( params . quality ,
channels ,
params . initialSampleRate , params . maxBufferSize , params . debugLevel ) ;
2012-09-09 16:57:42 +01:00
# else
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: No implementation available! " < < endl ;
2008-05-22 16:54:27 +00:00
abort ( ) ;
2012-09-09 16:57:42 +01:00
# endif
2008-05-22 16:54:27 +00:00
break ;
case 1 :
2011-01-07 21:46:36 +00:00
# ifdef HAVE_LIBSAMPLERATE
2020-10-21 15:05:14 +01:00
d = new Resamplers : : D_SRC
( params . quality ,
channels ,
params . initialSampleRate , params . maxBufferSize , params . debugLevel ) ;
2011-01-07 21:46:36 +00:00
# else
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: No implementation available! " < < endl ;
2011-01-07 21:46:36 +00:00
abort ( ) ;
# endif
2008-05-22 16:54:27 +00:00
break ;
case 2 :
2012-09-09 16:57:42 +01:00
# ifdef USE_SPEEX
2020-10-21 15:05:14 +01:00
d = new Resamplers : : D_Speex
( params . quality ,
channels ,
params . initialSampleRate , params . maxBufferSize , params . debugLevel ) ;
2012-09-09 16:57:42 +01:00
# else
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: No implementation available! " < < endl ;
2008-05-22 16:54:27 +00:00
abort ( ) ;
2012-09-09 16:57:42 +01:00
# endif
2008-05-22 16:54:27 +00:00
break ;
2011-01-07 21:46:36 +00:00
case 3 :
# ifdef HAVE_LIBRESAMPLE
2020-10-21 15:05:14 +01:00
d = new Resamplers : : D_Resample
( params . quality ,
channels ,
params . initialSampleRate , params . maxBufferSize , params . debugLevel ) ;
2011-01-07 21:46:36 +00:00
# else
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: No implementation available! " < < endl ;
2011-01-07 21:46:36 +00:00
abort ( ) ;
# endif
break ;
2008-05-22 16:54:27 +00:00
}
2011-03-19 12:41:38 +00:00
if ( ! d ) {
2020-10-21 15:05:14 +01:00
cerr < < " Resampler::Resampler: Internal error: No implementation selected "
< < endl ;
2011-03-19 12:41:38 +00:00
abort ( ) ;
}
2007-11-06 21:41:16 +00:00
}
Resampler : : ~ Resampler ( )
{
2008-05-22 16:54:27 +00:00
delete d ;
2007-11-06 21:41:16 +00:00
}
2008-05-22 16:54:27 +00:00
int
2020-10-21 15:05:14 +01:00
Resampler : : resample ( float * const R__ * const R__ out ,
int outcount ,
const float * const R__ * const R__ in ,
int incount ,
double ratio ,
bool final )
2007-11-06 21:41:16 +00:00
{
2008-05-22 16:54:27 +00:00
Profiler profiler ( " Resampler::resample " ) ;
2020-10-21 15:05:14 +01:00
return d - > resample ( out , outcount , in , incount , ratio , final ) ;
2007-11-06 21:41:16 +00:00
}
2010-03-24 09:44:51 +00:00
int
2020-10-21 15:05:14 +01:00
Resampler : : resampleInterleaved ( float * const R__ out ,
int outcount ,
const float * const R__ in ,
int incount ,
double ratio ,
bool final )
2010-03-24 09:44:51 +00:00
{
2020-10-21 15:05:14 +01:00
Profiler profiler ( " Resampler::resampleInterleaved " ) ;
return d - > resampleInterleaved ( out , outcount , in , incount , ratio , final ) ;
2010-03-24 09:44:51 +00:00
}
2009-09-17 13:01:21 +00:00
int
Resampler : : getChannelCount ( ) const
{
return d - > getChannelCount ( ) ;
}
2007-11-06 21:41:16 +00:00
void
Resampler : : reset ( )
{
2008-05-22 16:54:27 +00:00
d - > reset ( ) ;
2007-11-06 21:41:16 +00:00
}
}