20 #include <com/avpkit/ferry/Logger.h>
21 #include <com/avpkit/core/AudioResampler.h>
22 #include <com/avpkit/core/AudioSamples.h>
23 #include <com/avpkit/core/Global.h>
24 #include <com/avpkit/core/FfmpegIncludes.h>
28 VS_LOG_SETUP(VS_CPP_PACKAGE);
30 namespace com {
namespace avpkit {
namespace core
34 AudioResampler :: AudioResampler()
51 AudioResampler :: ~AudioResampler()
54 swr_free(&swrContext);
59 AudioResampler :: make(
60 int32_t outputChannels, int32_t inputChannels,
61 int32_t outputRate, int32_t inputRate
64 return make(outputChannels, inputChannels, outputRate, inputRate,
69 AudioResampler :: make(
70 int32_t outputChannels, int32_t inputChannels,
71 int32_t outputRate, int32_t inputRate,
75 return make(outputChannels, inputChannels, outputRate, inputRate,
81 AudioResampler :: make(
82 int32_t outputChannels, int32_t inputChannels,
83 int32_t outputRate, int32_t inputRate,
85 int32_t filterLen, int32_t log2PhaseCount,
86 bool linear,
double cutoff
89 AudioResampler* retval = 0;
91 if (outputChannels <= 0)
92 throw std::invalid_argument(
"outputChannels <= 0");
94 if (inputChannels <= 0)
95 throw std::invalid_argument(
"inputChannels <= 0");
98 throw std::invalid_argument(
"outputRate <= 0");
101 throw std::invalid_argument(
"inputRate <= 0");
104 throw std::invalid_argument(
"filterLen <= 0");
106 if (log2PhaseCount < 0)
107 throw std::invalid_argument(
"log2PhaseCount < 0");
110 throw std::invalid_argument(
"cutoffFrequency < 0");
112 retval = AudioResampler::make();
116 retval->swrContext = swr_alloc_set_opts(NULL,
117 av_get_default_channel_layout(outputChannels),
118 (
enum AVSampleFormat) outputFmt,
120 av_get_default_channel_layout(inputChannels),
121 (
enum AVSampleFormat) inputFmt,
125 if (retval->swrContext){
126 av_opt_set_int(retval->swrContext,
"phase_shift", log2PhaseCount, 0);
127 av_opt_set_double(retval->swrContext,
"cutoff", cutoff, 0);
128 av_opt_set_int(retval->swrContext,
"filter_size", filterLen, 0);
129 av_opt_set_int(retval->swrContext,
"linear_interp", linear, 0);
130 int init = swr_init(retval->swrContext);
133 throw std::invalid_argument(
"unable to init swr context in resampler");
135 retval->mOChannels = outputChannels;
136 retval->mOSampleRate = outputRate;
137 retval->mIChannels = inputChannels;
138 retval->mISampleRate = inputRate;
139 retval->mOFmt = outputFmt;
140 retval->mIFmt = inputFmt;
141 retval->mFilterLen = filterLen;
142 retval->mLog2PhaseCount = log2PhaseCount;
143 retval->mIsLinear = linear;
144 retval->mCutoff = cutoff;
146 VS_REF_RELEASE(retval);
150 catch (std::bad_alloc & e)
152 VS_LOG_ERROR(
"Error: %s", e.what());
153 VS_REF_RELEASE(retval);
156 catch (std::exception & e)
158 VS_LOG_ERROR(
"Error: %s", e.what());
159 VS_REF_RELEASE(retval);
167 VS_ASSERT(swrContext,
"no context");
174 VS_ASSERT(swrContext,
"no context");
181 VS_ASSERT(swrContext,
"no context");
188 VS_ASSERT(swrContext,
"no context");
198 int32_t numSamples = 0;
202 throw std::invalid_argument(
"input samples are not complete");
205 throw std::invalid_argument(
"unexpected input sample rate");
208 throw std::invalid_argument(
"unexpected # of input channels");
211 throw std::invalid_argument(
"unexpected sample format");
217 retval = getMinimumNumSamplesRequiredInOutputSamples(numSamples);
219 catch (std::invalid_argument & e)
221 VS_LOG_DEBUG(
"invalid argument: %s", e.what());
224 catch (std::exception & e)
226 VS_LOG_DEBUG(
"Unknown exception: %s", e.what());
240 throw std::invalid_argument(
"numSamples < 0 not allowed");
242 double conversionRatio = 1;
244 double top = mOSampleRate;
245 VS_ASSERT(top,
"should never be zero");
246 double bot = mISampleRate;
247 VS_ASSERT(bot,
"should never be zero");
248 conversionRatio = top/bot;
249 VS_ASSERT(conversionRatio > 0,
"the variables used should have been checked on construction");
251 if (conversionRatio <= 0)
252 throw std::invalid_argument(
"programmer error");
260 #define VS_FFMPEG_AUDIO_RESAMPLER_LEADIN 16
262 (int32_t)((numSamples * conversionRatio)+VS_FFMPEG_AUDIO_RESAMPLER_LEADIN+0.5);
264 catch (std::invalid_argument & e)
266 VS_LOG_DEBUG(
"invalid argument: %s", e.what());
269 catch (std::exception & e)
271 VS_LOG_DEBUG(
"Unknown exception: %s", e.what());
285 unsigned int sampleSize=0;
289 throw std::invalid_argument(
"no output samples");
291 if (outSamples == inSamples)
292 throw std::invalid_argument(
"resampling into the same IAudioSamples is not allowed");
295 outSamples->
setComplete(
false, 0, mOSampleRate, mOChannels,
301 throw std::invalid_argument(
"input samples are not complete");
304 throw std::invalid_argument(
"unexpected input sample rate");
307 throw std::invalid_argument(
"unexpected # of input channels");
310 throw std::invalid_argument(
"unexpected sample format");
322 int32_t neededSamples = getMinimumNumSamplesRequiredInOutputSamples(numSamples);
324 int32_t neededBytes = neededSamples * bytesPerOutputSample;
327 throw std::runtime_error(
"attempted to resize output buffer but failed");
330 int32_t gap = (neededSamples*bytesPerOutputSample)-outBufSize;
340 throw std::invalid_argument(
"not enough room in output buffer");
342 short * inBuf = inSamples ? inSamples->getRawSamples(0) : 0;
344 short *outBuf = outSamples->getRawSamples(0);
346 throw std::invalid_argument(
"could not get output bytes");
348 VS_ASSERT(swrContext,
"Should have been set at initialization");
350 throw std::invalid_argument(
"programmer error");
353 retval = swr_convert(swrContext, (uint8_t**)&outBuf, swr_get_out_samples(swrContext, numSamples), (
const uint8_t**)&inBuf, numSamples);
357 char string[2048*16+1];
359 for (i = 0; i <
sizeof(string)-1; i++)
364 for (i=0; i< FFMIN(numSamples, 2000);i++)
366 snprintf(
string+(5*i),
sizeof(
string)-5*i,
"%04hX.", inBuf[i]);
370 VS_LOG_DEBUG(
"Input Buffer (%d): %s", numSamples,
string);
372 for (i=0; i< FFMIN((
unsigned int)retval, 2000);i++)
374 snprintf(
string+(9*i),
sizeof(
string)-9*i,
"%04hX%04hX.",
375 outBuf[2*i], outBuf[2*i+1]);
376 if (outBuf[2*i] != 0 || outBuf[2*i+1] != 0)
379 VS_LOG_DEBUG(
"Output Buffer (%d): %s", retval,
string);
381 VS_LOG_DEBUG(
"Got an audio buffer with content");
391 pts = inSamples->
getPts();
402 mOSampleRate, mOChannels,
405 int expectedSamples = 0;
408 double top = mOSampleRate;
409 double bottom = mISampleRate;
410 double sampleOnlyConverstionRatio = top / bottom;
411 expectedSamples = (int)(numSamples * sampleOnlyConverstionRatio);
415 VS_LOG_TRACE(
"Got null samples; outputted all cached and set pts offset from %lld to 0",
417 expectedSamples = retval;
422 if (retval != expectedSamples)
426 int sampleDelta = retval - expectedSamples;
428 mPtsOffset += ptsDelta;
432 catch (std::invalid_argument & e)
434 VS_LOG_DEBUG(
"invalid argument: %s", e.what());
462 return mLog2PhaseCount;
virtual int resample(IAudioSamples *pOutputSamples, IAudioSamples *pInputSamples, int32_t numSamples)
Re-sample up to numSamples from inputSamples to outputSamples.
virtual int32_t getMinimumNumSamplesRequiredInOutputSamples(IAudioSamples *inSamples)
Get the minimum number of samples that must be placeable in an output set of samples in order for a r...
virtual int32_t getFilterLen()
Get the length of each filter in the resampler filter bank.
virtual double getCutoffFrequency()
What is the cuttoff frequency used?
virtual int getInputChannels()
number of channels expected in input audio.
virtual int getOutputRate()
sample rate of output audio.
virtual IAudioSamples::Format getInputFormat()
Get the sample format we expect to resample from.
virtual bool isLinear()
Are we linearly interpolating between filters?
virtual int getOutputChannels()
number of channels in output audio.
virtual int32_t getLog2PhaseCount()
Get log2(number of entries in filter bank).
virtual IAudioSamples::Format getOutputFormat()
Get the sample format we expect to resample to.
virtual int getInputRate()
sample rate expected in input audio.
virtual int32_t getSampleRate()
Find the sample rate of the samples in this audio buffer.
virtual Format getFormat()
Find the Format of the samples in this buffer.
virtual int32_t getChannels()
Return the number of channels of the samples in this buffer.
virtual int32_t ensureCapacity(int32_t capacityInBytes)
Called by decoder before decoding to ensure sufficient space.
virtual void setComplete(bool complete, int32_t numSamples, int32_t sampleRate, int32_t channels, Format sampleFmt, int64_t pts)
Call this if you modify the samples and are now done.
virtual int64_t getPts()
What is the Presentation Time Stamp of this set of audio samples.
virtual int32_t getMaxBufferSize()
virtual int32_t getNumSamples()
Get the number of samples in this video.
virtual int32_t getSampleBitDepth()
Find out the bit-depth of the samples in this buffer.
virtual bool isComplete()
Returns whether or not we think this buffer has been filled with data.
static const int64_t NO_PTS
A value that means no time stamp is set for a given object.
A set of raw (decoded) samples, plus a timestamp for when to play those samples relative to other ite...
virtual int32_t getChannels()=0
Return the number of channels of the samples in this buffer.
static int32_t findSampleBitDepth(Format format)
A convenience method that returns the # of bits in a given format.
virtual int32_t getSampleRate()=0
Find the sample rate of the samples in this audio buffer.
virtual bool isComplete()=0
Returns whether or not we think this buffer has been filled with data.
virtual Format getFormat()=0
Find the Format of the samples in this buffer.
virtual int32_t getNumSamples()=0
Get the number of samples in this video.
Format
The format we use to represent audio.
static int64_t samplesToDefaultPts(int64_t samples, int sampleRate)
Converts a number of samples at a given sampleRate into Microseconds.
This library contains routines used by AVPKit libraries for "ferry"ing Java objects to and from nativ...
WARNING: Do not use logging in this class, and do not set any static file variables to values other t...