mirror of
https://github.com/pschatzmann/arduino-audio-tools.git
synced 2024-09-21 02:17:31 +00:00
Merge branch 'main' of https://github.com/pschatzmann/arduino-audio-tools
This commit is contained in:
commit
fab4a76d57
6
docs/index.html
Normal file
6
docs/index.html
Normal file
@ -0,0 +1,6 @@
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=https://pschatzmann.github.io/arduino-audio-tools/modules.html" />
|
||||
</head>
|
||||
<body>
|
||||
<p>If you are not redirected, <a href="https://pschatzmann.github.io/arduino-audio-tools/modules.html">click here</a>.</p>
|
||||
</body>
|
@ -69,7 +69,7 @@ adcConfig.adc_channels[1] = ADC_CHANNEL_5;
|
||||
```
|
||||
|
||||
## ADC unit 1 channels on common ESP32 boards
|
||||
Audio tools supports ADC Unit 1 only.
|
||||
Audio tools continous ADC framewaork supports ADC Unit 1 only.
|
||||
|
||||
### Sparkfun ESP32 Thing Plus (ESP32)
|
||||
- A2, ADC1_CH6
|
||||
@ -78,6 +78,14 @@ Audio tools supports ADC Unit 1 only.
|
||||
- 32, ADC1_CH4
|
||||
- 33, ADC1_CH5
|
||||
|
||||
### Sparkfun ESP32 Thing Plus C (ESP32)
|
||||
- A2, ADC1_CH6
|
||||
- A3, ADC1_CH3
|
||||
- A4, ADC1_CH0
|
||||
- A5, ADC1_CH7
|
||||
- 32/6, ADC1_CH4
|
||||
- 33/10, ADC1_CH5
|
||||
|
||||
### Sparkfun ESP32 Qwiic Pocket Development (ESP32C6)
|
||||
- 2, ADC1_CH2
|
||||
- 3, ADC1_CH3
|
||||
|
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file channel-converter-avg.ino
|
||||
* @brief Test calculating pairwise average of channels
|
||||
* @author Urs Utzinger
|
||||
* @copyright GPLv3
|
||||
**/
|
||||
|
||||
#include "AudioTools.h"
|
||||
|
||||
AudioInfo info1(44100, 1, 16);
|
||||
AudioInfo info2(44100, 2, 16);
|
||||
SineWaveGenerator<int16_t> sineWave1(32000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
SineWaveGenerator<int16_t> sineWave2(32000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
GeneratedSoundStream<int16_t> sound1(sineWave1); // stream generated from sine wave1
|
||||
GeneratedSoundStream<int16_t> sound2(sineWave2); // stream generated from sine wave2
|
||||
InputMerge<int16_t> imerge; // merge two inputs to stereo
|
||||
ChannelAvg averager; // channel averager
|
||||
ConverterStream<int16_t> averaged_stream(imerge, averager); // pipe the sound to the averager
|
||||
CsvOutput<int16_t> serial_out(Serial); // serial output
|
||||
StreamCopy copier(serial_out, averaged_stream); // stream the binner output to serial port
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
while(!Serial); // wait for Serial to be ready
|
||||
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
|
||||
|
||||
// Setup sine waves
|
||||
sineWave1.begin(info1, N_B4);
|
||||
sineWave2.begin(info1, N_B5);
|
||||
|
||||
// Merge input to stereo
|
||||
imerge.add(sound1);
|
||||
imerge.add(sound2);
|
||||
imerge.begin(info2);
|
||||
|
||||
// Define CSV Output
|
||||
serial_out.begin(info1);
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out with conversion
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file channel-converter-avg.ino
|
||||
* @brief Test calculating average of two channels
|
||||
* @author Urs Utzinger
|
||||
* @copyright GPLv3
|
||||
**/
|
||||
|
||||
#include "AudioTools.h"
|
||||
|
||||
#define BINSIZE 4
|
||||
|
||||
AudioInfo info1(44100, 1, 16);
|
||||
AudioInfo info2(44100, 2, 16);
|
||||
AudioInfo info_out(44100/BINSIZE, 2, 16);
|
||||
SineWaveGenerator<int16_t> sineWave1(32000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
SineWaveGenerator<int16_t> sineWave2(32000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
GeneratedSoundStream<int16_t> sound1(sineWave1); // stream generated from sine wave1
|
||||
GeneratedSoundStream<int16_t> sound2(sineWave2); // stream generated from sine wave2
|
||||
InputMerge<int16_t> imerge; // merge two inputs to stereo
|
||||
Bin binner; // channel averager
|
||||
ConverterStream<int16_t> binned_stream(imerge, binner); // pipe the sound to the averager
|
||||
CsvOutput<int16_t> serial_out(Serial); // serial output
|
||||
StreamCopy copier(serial_out, binned_stream); // stream the binner output to serial port
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
while(!Serial); // wait for Serial to be ready
|
||||
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
|
||||
|
||||
// Setup sine waves
|
||||
sineWave1.begin(info1, N_B4);
|
||||
sineWave2.begin(info1, N_B5);
|
||||
|
||||
// Merge input to stereo
|
||||
imerge.add(sound1);
|
||||
imerge.add(sound2);
|
||||
imerge.begin(info2);
|
||||
|
||||
// Configure binning
|
||||
binner.setChannels(2);
|
||||
binner.setBits(16);
|
||||
binner.setBinSize(BINSIZE);
|
||||
binner.setAverage(true);
|
||||
|
||||
// Define CSV Output
|
||||
serial_out.begin(info_out);
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out with conversion
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file channel-converter-bin-diff.ino
|
||||
* @author Urs Utzinger
|
||||
* @brief On two channels reduce number of samples by binning, then compute difference between two channels
|
||||
* @copyright GPLv3
|
||||
**/
|
||||
|
||||
#include "AudioTools.h"
|
||||
|
||||
#define BINSIZE 4
|
||||
|
||||
AudioInfo info1(44100, 1, 16);
|
||||
AudioInfo info2(44100, 2, 16);
|
||||
AudioInfo info_out(44100/BINSIZE, 1, 16);
|
||||
SineWaveGenerator<int16_t> sineWave1(16000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
SineWaveGenerator<int16_t> sineWave2(16000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
GeneratedSoundStream<int16_t> sound1(sineWave1); // stream generated from sine wave
|
||||
GeneratedSoundStream<int16_t> sound2(sineWave2); // stream generated from sine wave
|
||||
InputMerge<int16_t> imerge;
|
||||
ChannelBinDiff bindiffer; // Binning each channel by average length, setup see below
|
||||
ConverterStream<int16_t> converted_stream(imerge, bindiffer); // pipe the merged sound to the converter
|
||||
CsvOutput<int16_t> serial_out(Serial); // serial output
|
||||
StreamCopy copier(serial_out, converted_stream); // stream the binner output to serial port
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Debug); // Info, Warning, Error, Debug
|
||||
|
||||
// Setup sine wave
|
||||
sineWave1.begin(info1, N_B4);
|
||||
sineWave2.begin(info1, N_B5);
|
||||
|
||||
// Merge input to stereo
|
||||
imerge.add(sound1);
|
||||
imerge.add(sound2);
|
||||
imerge.begin(info2);
|
||||
|
||||
// Setup binning
|
||||
bindiffer.setChannels(2);
|
||||
bindiffer.setBits(16);
|
||||
bindiffer.setBinSize(BINSIZE);
|
||||
bindiffer.setAverage(true);
|
||||
|
||||
// Define CSV Output
|
||||
serial_out.begin(info_out);
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out with conversion
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @file channel-converter-decimate.ino
|
||||
* @author Urs Utzinger
|
||||
* @brief Reduce samples by binning; which is summing consecutive samples and optionally dividing by the number of samples summed.
|
||||
* @copyright GPLv3
|
||||
**/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#define FACTOR 4
|
||||
|
||||
AudioInfo info1(44100, 1, 16);
|
||||
AudioInfo info2(44100, 2, 16);
|
||||
AudioInfo infoO(44100/FACTOR, 2, 16);
|
||||
SineWaveGenerator<int16_t> sineWave1(16000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
SineWaveGenerator<int16_t> sineWave2(16000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
GeneratedSoundStream<int16_t> sound1(sineWave1); // stream generated from sine wave
|
||||
GeneratedSoundStream<int16_t> sound2(sineWave2); // stream generated from sine wave
|
||||
InputMerge<int16_t> imerge;
|
||||
Decimate decimater; // decimate by 4 on 1 channel
|
||||
ConverterStream<int16_t> decimated_stream(imerge, decimater); // pipe the sound to the binner
|
||||
CsvOutput<int16_t> serial_out(Serial); // serial output
|
||||
StreamCopy copier(serial_out, decimated_stream); // stream the binner output to serial port
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
|
||||
|
||||
//
|
||||
decimater.setChannels(2);
|
||||
decimater.setFactor(FACTOR);
|
||||
|
||||
// Merge input to stereo
|
||||
imerge.add(sound1);
|
||||
imerge.add(sound2);
|
||||
imerge.begin(info2);
|
||||
|
||||
// Setup sine wave
|
||||
sineWave1.begin(info1, N_B4);
|
||||
sineWave2.begin(info1, N_B5);
|
||||
|
||||
// Define CSV Output
|
||||
serial_out.begin(infoO);
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out with conversion
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file channel-converter-diff.ino
|
||||
* @brief Test calculating parwise difference of channels
|
||||
* @author Urs Utzinger
|
||||
* @copyright GPLv3
|
||||
**/
|
||||
|
||||
#include "AudioTools.h"
|
||||
|
||||
AudioInfo info1(44100, 1, 16);
|
||||
AudioInfo info2(44100, 2, 16);
|
||||
SineWaveGenerator<int16_t> sineWave1(16000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
SineWaveGenerator<int16_t> sineWave2(16000); // subclass of SoundGenerator with max amplitude of 32000
|
||||
GeneratedSoundStream<int16_t> sound1(sineWave1); // stream generated from sine wave1
|
||||
GeneratedSoundStream<int16_t> sound2(sineWave2); // stream generated from sine wave2
|
||||
InputMerge<int16_t> imerge; // merge two inputs to stereo
|
||||
ChannelDiff differ; // channel averager
|
||||
ConverterStream<int16_t> diffed_stream(imerge, differ); // pipe the sound to the averager
|
||||
CsvOutput<int16_t> serial_out(Serial); // serial output
|
||||
StreamCopy copier(serial_out, diffed_stream); // stream the binner output to serial port
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
while(!Serial); // wait for Serial to be ready
|
||||
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
|
||||
|
||||
// Setup sine waves
|
||||
sineWave1.begin(info1, N_B4);
|
||||
sineWave2.begin(info1, N_B5);
|
||||
|
||||
// Merge input to stereo
|
||||
imerge.add(sound1);
|
||||
imerge.add(sound2);
|
||||
imerge.begin(info2);
|
||||
|
||||
// Define CSV Output
|
||||
serial_out.begin(info1);
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out with conversion
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
298
jupyter/Jupyter.ipynb
Normal file
298
jupyter/Jupyter.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -12,7 +12,7 @@
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
# define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1
|
||||
# define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_6, ADC_CHANNEL_7}
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_7, ADC_CHANNEL_0, ADC_CHANNEL_3, ADC_CHANNEL_6, ADC_CHANNEL_4, ADC_CHANNEL_5}
|
||||
# define AUDIO_ADC_GET_CHANNEL(p_data) ((p_data)->type1.channel)
|
||||
# define AUDIO_ADC_GET_DATA(p_data) ((p_data)->type1.data)
|
||||
# define HAS_ESP32_DAC
|
||||
@ -21,20 +21,20 @@
|
||||
# define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
|
||||
# define AUDIO_ADC_GET_CHANNEL(p_data) ((p_data)->type2.channel)
|
||||
# define AUDIO_ADC_GET_DATA(p_data) ((p_data)->type2.data)
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_2, ADC_CHANNEL_3}
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_7, ADC_CHANNEL_0, ADC_CHANNEL_3, ADC_CHANNEL_6, ADC_CHANNEL_4, ADC_CHANNEL_5}
|
||||
# define HAS_ESP32_DAC
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
|
||||
# define ADC_CONV_MODE ADC_CONV_ALTER_UNIT //ESP32C3 only supports alter mode
|
||||
# define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
|
||||
# define AUDIO_ADC_GET_CHANNEL(p_data) ((p_data)->type2.channel)
|
||||
# define AUDIO_ADC_GET_DATA(p_data) ((p_data)->type2.data)
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_2, ADC_CHANNEL_3}
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_7, ADC_CHANNEL_0, ADC_CHANNEL_3, ADC_CHANNEL_6, ADC_CHANNEL_4, ADC_CHANNEL_5}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
# define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1
|
||||
# define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
|
||||
# define AUDIO_ADC_GET_CHANNEL(p_data) ((p_data)->type2.channel)
|
||||
# define AUDIO_ADC_GET_DATA(p_data) ((p_data)->type2.data)
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_2, ADC_CHANNEL_3} // or channel 4 & 5
|
||||
# define ADC_CHANNELS {ADC_CHANNEL_8, ADC_CHANNEL_9, ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_4, ADC_CHANNEL_5}
|
||||
#endif
|
||||
|
||||
// #define GET_ADC_UNIT_FROM_CHANNEL(x) ((x >> 3) & 0x1)
|
||||
@ -77,8 +77,7 @@ class AnalogConfigESP32V1 : public AudioInfo {
|
||||
adc_digi_output_format_t adc_output_type = ADC_OUTPUT_TYPE;
|
||||
uint8_t adc_attenuation = ADC_ATTEN_DB_12; // full voltage range of 3.9V
|
||||
uint8_t adc_bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
|
||||
/// ESP32: ADC_CHANNEL_6, ADC_CHANNEL_7; others ADC_CHANNEL_2, ADC_CHANNEL_3
|
||||
adc_channel_t adc_channels[2] = ADC_CHANNELS;
|
||||
adc_channel_t adc_channels[6] = ADC_CHANNELS;
|
||||
|
||||
/// Default constructor
|
||||
AnalogConfigESP32V1(RxTxMode rxtxMode=TX_MODE) {
|
||||
|
@ -39,7 +39,7 @@ class BaseConverter {
|
||||
*/
|
||||
class NOPConverter : public BaseConverter {
|
||||
public:
|
||||
virtual size_t convert(uint8_t(*src), size_t size) { return size; };
|
||||
size_t convert(uint8_t(*src), size_t size) override { return size; };
|
||||
};
|
||||
|
||||
/**
|
||||
@ -110,7 +110,7 @@ class ConverterAutoCenterT : public BaseConverter {
|
||||
this->is_dynamic = isDynamic;
|
||||
}
|
||||
|
||||
size_t convert(uint8_t(*src), size_t byte_count) {
|
||||
size_t convert(uint8_t(*src), size_t byte_count) override {
|
||||
size_t size = byte_count / channels / sizeof(T);
|
||||
T *sample = (T *)src;
|
||||
setup((T *)src, size);
|
||||
@ -194,7 +194,10 @@ class ConverterAutoCenter : public BaseConverter {
|
||||
begin(channels, bitsPerSample);
|
||||
}
|
||||
~ConverterAutoCenter() {
|
||||
if (p_converter != nullptr) delete p_converter;
|
||||
if (p_converter != nullptr) {
|
||||
delete p_converter;
|
||||
p_converter = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void begin(int channels, int bitsPerSample, bool isDynamic = false) {
|
||||
@ -241,7 +244,7 @@ class ConverterSwitchLeftAndRight : public BaseConverter {
|
||||
public:
|
||||
ConverterSwitchLeftAndRight(int channels = 2) { this->channels = channels; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t byte_count) {
|
||||
size_t convert(uint8_t *src, size_t byte_count) override {
|
||||
if (channels == 2) {
|
||||
int size = byte_count / channels / sizeof(T);
|
||||
T *sample = (T *)src;
|
||||
@ -361,7 +364,7 @@ class ConverterToInternalDACFormat : public BaseConverter {
|
||||
public:
|
||||
ConverterToInternalDACFormat(int channels = 2) { this->channels = channels; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t byte_count) {
|
||||
size_t convert(uint8_t *src, size_t byte_count) override {
|
||||
int size = byte_count / channels / sizeof(T);
|
||||
T *sample = (T *)src;
|
||||
for (int i = 0; i < size; i++) {
|
||||
@ -486,16 +489,21 @@ class DecimateT : public BaseConverter {
|
||||
DecimateT(int factor, int channels) {
|
||||
setChannels(channels);
|
||||
setFactor(factor);
|
||||
count = 0; // Initialize count to 0
|
||||
}
|
||||
|
||||
/// Defines the number of channels
|
||||
void setChannels(int channels) { this->channels = channels; }
|
||||
|
||||
/// Sets the factor: e.g. with 4 we keep every forth sample
|
||||
/// Sets the factor: e.g. with 4 we keep every fourth sample
|
||||
void setFactor(int factor) { this->factor = factor; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
|
||||
assert(size % (sizeof(T) * channels) == 0); // Ensure proper buffer size
|
||||
|
||||
int frame_count = size / (sizeof(T) * channels);
|
||||
T *p_target = (T *)target;
|
||||
T *p_source = (T *)src;
|
||||
@ -504,23 +512,24 @@ class DecimateT : public BaseConverter {
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
if (++count == factor) {
|
||||
count = 0;
|
||||
// only keep even samples
|
||||
// Only keep every "factor" samples
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
*p_target++ = p_source[i + ch];
|
||||
*p_target++ = p_source[i * channels + ch]; // Corrected indexing
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LOGI("%d: %d -> %d ",factor, (int)size, (int)result_size);
|
||||
return result_size;
|
||||
}
|
||||
|
||||
operator bool() { return factor > 1; };
|
||||
operator bool() { return factor > 1; }
|
||||
|
||||
protected:
|
||||
int channels = 2;
|
||||
int factor = 1;
|
||||
uint16_t count = 0;
|
||||
uint16_t count;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -570,106 +579,175 @@ class Decimate : public BaseConverter {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Provides a reduced sampling rate through binning
|
||||
* @brief We reduce the number of samples in a datastream by summing (binning) or averaging.
|
||||
* This will result in the same number of channels but binSize times less samples.
|
||||
* If Average is true the sum is divided by binSize.
|
||||
* @author Urs Utzinger
|
||||
* @ingroup convert
|
||||
* @tparam T
|
||||
*/
|
||||
|
||||
// Helper template to define the integer type for the summation based on input
|
||||
// data type T
|
||||
template <typename T>
|
||||
struct AppropriateSumType;
|
||||
struct AppropriateSumType {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AppropriateSumType<int8_t> {
|
||||
using type = int16_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AppropriateSumType<int16_t> {
|
||||
using type = int32_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AppropriateSumType<int24_t> {
|
||||
using type = int32_t;
|
||||
using type = int32_t; // Assuming int24_t is a custom 24-bit integer type
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AppropriateSumType<int32_t> {
|
||||
using type = int64_t;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Provides reduced sampling rates through binning: typed implementation
|
||||
* @ingroup convert
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class BinT : public BaseConverter {
|
||||
public:
|
||||
BinT() = default;
|
||||
BinT(int binSize, int channels, bool average) {
|
||||
setChannels(channels);
|
||||
setBinSize(binSize);
|
||||
setAverage(average);
|
||||
this->partialBinSize = 0;
|
||||
this->partialBin = new T[channels];
|
||||
std::fill(this->partialBin, this->partialBin + channels, 0); // Initialize partialBin with zeros
|
||||
}
|
||||
/// Defines the number of channels
|
||||
|
||||
~BinT() {
|
||||
delete[] this->partialBin;
|
||||
}
|
||||
|
||||
void setChannels(int channels) { this->channels = channels; }
|
||||
|
||||
/// Sets the bins: e.g. with 4 we sum 4 sample
|
||||
void setBinSize(int binSize) { this->binSize = binSize; }
|
||||
|
||||
/// Enables averaging: e.g. when true it divides the sum by number of bins
|
||||
void setAverage(bool average) { this->average = average; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
int frame_count = size / (sizeof(T) * channels);
|
||||
// The binning takes the following into account
|
||||
// 1) if size is too small it will add up data to partialBin and return 0 size
|
||||
// 2) if there is sufficient data to fill Bins but there is partial data remaining it will be added to the partial Bin
|
||||
// 3) if there was previous partial Bin it will be filled with the new data
|
||||
// 4) if there is insufficient new data to fill the partial Bin it will fill the partial Bin with the new data
|
||||
LOGD("Binning %d samples of %d size buffer", size / sizeof(T), size);
|
||||
|
||||
assert(size % (sizeof(T) * channels) == 0); // Ensure proper buffer size
|
||||
|
||||
int sample_count = size / (sizeof(T) * channels); // new available samples in each channel
|
||||
int total_samples = partialBinSize + sample_count; // total samples available for each channel including previous number of sample in partial bin
|
||||
int bin_count = total_samples / binSize; // number of bins we can make
|
||||
int remaining_samples = total_samples % binSize; // remaining samples after binning
|
||||
T *p_target = (T *)target;
|
||||
T *p_source = (T *)src;
|
||||
size_t result_size = 0;
|
||||
|
||||
// Allocate stack memory for sums to avoid dynamic allocation overhead.
|
||||
// Ensure you have enough stack space or adjust accordingly for your
|
||||
// environment.
|
||||
// Allocate sum for each channel with appropriate type
|
||||
typename AppropriateSumType<T>::type sums[channels];
|
||||
int current_sample = 0; // current sample index
|
||||
|
||||
// Is there a partial bin from the previous call?
|
||||
// ----
|
||||
if (partialBinSize > 0) {
|
||||
|
||||
int samples_needed = binSize - partialBinSize;
|
||||
bool have_enough_samples = (samples_needed < sample_count);
|
||||
int samples_to_bin = have_enough_samples ? samples_needed : sample_count;
|
||||
|
||||
for (int i = 0; i < frame_count; i += binSize) {
|
||||
// Initialize sums for each channel to the first element in the bin
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] = (i * channels + ch < frame_count * channels)
|
||||
? p_source[i * channels + ch]
|
||||
: static_cast<T>(0);
|
||||
sums[ch] = partialBin[ch];
|
||||
}
|
||||
|
||||
// Sum up binSize number of samples for each channel, starting from the
|
||||
// second sample in the bin
|
||||
for (int j = 1; j < binSize && (i + j) < frame_count; j++) {
|
||||
for (int j = 0; j < samples_to_bin; j++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] += p_source[(i + j) * channels + ch];
|
||||
sums[ch] += p_source[current_sample * channels + ch];
|
||||
}
|
||||
current_sample++;
|
||||
}
|
||||
|
||||
// Compute average or sum for each channel and write to target buffer
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
if (have_enough_samples) {
|
||||
// Store the completed bin
|
||||
if (average) {
|
||||
T avg = static_cast<T>(sums[ch] / binSize);
|
||||
*p_target++ = avg;
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>(sums[ch] / binSize);
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
} else {
|
||||
*p_target++ = static_cast<T>(sums[ch]);
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>(sums[ch]);
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
}
|
||||
result_size += sizeof(T) * channels;
|
||||
partialBinSize = 0;
|
||||
} else {
|
||||
// Not enough samples to complete the bin, update partialBin
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
partialBin[ch] = sums[ch];
|
||||
}
|
||||
|
||||
// LOGI("%d: %d -> %d avg:%s", binSize, (int)size, (int)result_size, average
|
||||
// ? "on" : "off");
|
||||
partialBinSize += current_sample;
|
||||
return result_size;
|
||||
}
|
||||
}
|
||||
|
||||
operator bool() { return binSize > 1; };
|
||||
// Fill bins
|
||||
// ----
|
||||
for (int i = 0; i < bin_count; i++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] = p_source[current_sample * channels + ch]; // Initialize sums with first value in the input buffer
|
||||
}
|
||||
|
||||
for (int j = 1; j < binSize; j++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] += p_source[(current_sample + j) * channels + ch];
|
||||
}
|
||||
}
|
||||
current_sample += binSize;
|
||||
|
||||
// Store the bin result
|
||||
if (average) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>(sums[ch] / binSize);
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
} else {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>(sums[ch]);
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the remaining samples in the partial bin
|
||||
// ----
|
||||
for (int i = 0; i < remaining_samples; i++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
partialBin[ch] += p_source[(current_sample + i) * channels + ch];
|
||||
}
|
||||
}
|
||||
partialBinSize = remaining_samples;
|
||||
|
||||
return result_size;
|
||||
}
|
||||
|
||||
protected:
|
||||
int channels = 2;
|
||||
int binSize = 1;
|
||||
bool average = true;
|
||||
uint16_t count = 0;
|
||||
T *partialBin;
|
||||
int partialBinSize;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -681,17 +759,15 @@ class Bin : public BaseConverter {
|
||||
public:
|
||||
Bin() = default;
|
||||
Bin(int binSize, int channels, bool average, int bits_per_sample) {
|
||||
setBinSize(binSize);
|
||||
setChannels(channels);
|
||||
setBinSize(binSize);
|
||||
setAverage(average);
|
||||
setBits(bits_per_sample);
|
||||
}
|
||||
/// Defines the number of channels
|
||||
|
||||
void setChannels(int channels) { this->channels = channels; }
|
||||
void setBits(int bits) { this->bits = bits; }
|
||||
/// Sets the binning size: e.g. with 4 we sum 4 samples
|
||||
void setBinSize(int binSize) { this->binSize = binSize; }
|
||||
/// Enables averaging: e.g. when true it divides the sum by number of bins
|
||||
void setAverage(bool average) { this->average = average; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
@ -718,11 +794,8 @@ class Bin : public BaseConverter {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
operator bool() { return binSize > 1; };
|
||||
|
||||
protected:
|
||||
int channels = 2;
|
||||
int bits = 16;
|
||||
@ -730,6 +803,380 @@ class Bin : public BaseConverter {
|
||||
bool average = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief We calculate the difference between pairs of channels in a datastream.
|
||||
* E.g. if we have 4 channels we end up with 2 channels.
|
||||
* The channels will be
|
||||
* channel_1 - channel_2
|
||||
* channel_3 - channel_4
|
||||
* This is similar to background subtraction between two channels but will
|
||||
* also work for quadric, sexic or octic audio.
|
||||
* This will not work if you provide single channel data!
|
||||
* @author Urs Utzinger
|
||||
* @ingroup convert
|
||||
* @tparam T
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class ChannelDiffT : public BaseConverter {
|
||||
public:
|
||||
ChannelDiffT() {}
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) override { return convert(src, src, size); }
|
||||
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
LOGD("convert %d samples of %d size buffer", size / sizeof(T), size);
|
||||
|
||||
// Ensure the buffer size is even for pairs of channels
|
||||
assert(size % (sizeof(T) * 2) == 0);
|
||||
|
||||
int sample_count = size / (sizeof(T) * 2); // Each pair of channels produces one output sample
|
||||
T *p_result = (T *)target;
|
||||
T *p_source = (T *)src;
|
||||
|
||||
for (int i = 0; i < sample_count; i++) {
|
||||
*p_result++ = *p_source++ - *p_source++;
|
||||
}
|
||||
|
||||
return sizeof(T) * sample_count;
|
||||
}
|
||||
};
|
||||
|
||||
class ChannelDiff : public BaseConverter {
|
||||
public:
|
||||
ChannelDiff() = default;
|
||||
ChannelDiff(int bitsPerSample) {
|
||||
setBits(bitsPerSample);
|
||||
}
|
||||
void setBits(int bits) { this->bits = bits; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
switch (bits) {
|
||||
case 8: {
|
||||
ChannelDiffT<int8_t> cd8;
|
||||
return cd8.convert(target, src, size);
|
||||
}
|
||||
case 16: {
|
||||
ChannelDiffT<int16_t> cd16;
|
||||
return cd16.convert(target, src, size);
|
||||
}
|
||||
case 24: {
|
||||
ChannelDiffT<int24_t> cd24;
|
||||
return cd24.convert(target, src, size);
|
||||
}
|
||||
case 32: {
|
||||
ChannelDiffT<int32_t> cd32;
|
||||
return cd32.convert(target, src, size);
|
||||
}
|
||||
default: {
|
||||
LOGE("Number of bits %d not supported.", bits);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int bits = 16;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief We average pairs of channels in a datastream.
|
||||
* E.g. if we have 4 channels we end up with 2 channels.
|
||||
* The channels will be
|
||||
* (channel_1 + channel_2)/2
|
||||
* (channel_3 - channel_4)/2.
|
||||
* This is equivalent of stereo to mono conversion but will
|
||||
* also work for quadric, sexic or octic audio.
|
||||
* This will not work if you provide single channel data!
|
||||
* @author Urs Utzinger
|
||||
* @ingroup convert
|
||||
* @tparam T
|
||||
*/
|
||||
template <typename T>
|
||||
class ChannelAvgT : public BaseConverter {
|
||||
public:
|
||||
ChannelAvgT() {}
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) override { return convert(src, src, size); }
|
||||
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
LOGD("convert %d samples of %d size buffer", size / sizeof(T), size);
|
||||
|
||||
assert(size % (sizeof(T) * 2) == 0); // Ensure even number of samples for pairs
|
||||
|
||||
int sample_count = size / (sizeof(T) * 2); // Each pair of channels produces one output sample
|
||||
T *p_result = (T *)target;
|
||||
T *p_source = (T *)src;
|
||||
|
||||
for (int i = 0; i < sample_count; i++) {
|
||||
*p_result++ = (*p_source++ + *p_source++) / 2; // Average the pair of channels
|
||||
}
|
||||
|
||||
return sizeof(T) * sample_count;
|
||||
}
|
||||
};
|
||||
|
||||
class ChannelAvg : public BaseConverter {
|
||||
public:
|
||||
ChannelAvg() = default;
|
||||
ChannelAvg(int bitsPerSample) {
|
||||
setBits(bitsPerSample);
|
||||
}
|
||||
void setBits(int bits) { this->bits = bits; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
switch (bits) {
|
||||
case 8: {
|
||||
ChannelAvgT<int8_t> ca8;
|
||||
return ca8.convert(target, src, size);
|
||||
}
|
||||
case 16: {
|
||||
ChannelAvgT<int16_t> ca16;
|
||||
return ca16.convert(target, src, size);
|
||||
}
|
||||
case 24: {
|
||||
ChannelAvgT<int24_t> ca24;
|
||||
return ca24.convert(target, src, size);
|
||||
}
|
||||
case 32: {
|
||||
ChannelAvgT<int32_t> ca32;
|
||||
return ca32.convert(target, src, size);
|
||||
}
|
||||
default: {
|
||||
LOGE("Number of bits %d not supported.", bits);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int bits = 16;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief We first bin the channels then we calculate the difference between pairs of channels in a datastream.
|
||||
* E.g. For binning, if we bin 4 samples in each channel we will have 4 times less samples per channel
|
||||
* E.g. For subtracting if we have 4 channels we end up with 2 channels.
|
||||
* The channels will be
|
||||
* channel_1 - channel_2
|
||||
* channel_3 - channel_4
|
||||
* This is the same as combining binning and subtracting channels.
|
||||
* This will not work if you provide single channel data!
|
||||
* @author Urs Utzinger
|
||||
* @ingroup convert
|
||||
* @tparam T
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class ChannelBinDiffT : public BaseConverter {
|
||||
public:
|
||||
ChannelBinDiffT() = default;
|
||||
ChannelBinDiffT(int binSize, int channels, bool average) {
|
||||
setChannels(channels);
|
||||
setBinSize(binSize);
|
||||
setAverage(average);
|
||||
this->partialBinSize = 0;
|
||||
this->partialBin = new T[channels];
|
||||
std::fill(this->partialBin, this->partialBin + channels, 0); // Initialize partialBin with zeros
|
||||
}
|
||||
|
||||
~ChannelBinDiffT() {
|
||||
delete[] this->partialBin;
|
||||
}
|
||||
|
||||
void setChannels(int channels) {
|
||||
assert((channels % 2) == 0); // Ensure even channel size
|
||||
this->channels = channels;
|
||||
}
|
||||
void setBinSize(int binSize) { this->binSize = binSize; }
|
||||
void setAverage(bool average) { this->average = average; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
// The binning works the same as in the BinT class
|
||||
// Here we add subtraction before we store the bins
|
||||
LOGD("Binning and Subtracting %d samples of %d size buffer", size / sizeof(T), size);
|
||||
|
||||
assert(size % (sizeof(T) * channels) == 0); // Ensure proper buffer size
|
||||
|
||||
int sample_count = size / (sizeof(T) * channels); // new available samples in each channel
|
||||
int total_samples = partialBinSize + sample_count; // total samples available for each channel including previous number of sample in partial bin
|
||||
int bin_count = total_samples / binSize; // number of bins we can make
|
||||
int remaining_samples = total_samples % binSize; // remaining samples after binning
|
||||
T *p_target = (T *)target;
|
||||
T *p_source = (T *)src;
|
||||
size_t result_size = 0;
|
||||
|
||||
// Allocate sum for each channel with appropriate type
|
||||
typename AppropriateSumType<T>::type sums[channels];
|
||||
int current_sample = 0; // current sample index
|
||||
|
||||
// Is there a partial bin from the previous call?
|
||||
// ----
|
||||
if (partialBinSize > 0) {
|
||||
|
||||
LOGD("Deal with partial bins");
|
||||
|
||||
int samples_needed = binSize - partialBinSize;
|
||||
bool have_enough_samples = (samples_needed < sample_count);
|
||||
int samples_to_bin = have_enough_samples ? samples_needed : sample_count;
|
||||
|
||||
// initialize
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] = partialBin[ch];
|
||||
}
|
||||
|
||||
// continue binning
|
||||
for (int j = 0; j < samples_to_bin; j++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] += p_source[current_sample * channels + ch];
|
||||
}
|
||||
current_sample++;
|
||||
}
|
||||
|
||||
// store the bin results or update the partial bin
|
||||
if (have_enough_samples) {
|
||||
// Subtract two channels and store the completed bin
|
||||
if (average) {
|
||||
for (int ch = 0; ch < channels; ch+=2) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>((sums[ch] - sums[ch+1]) / binSize);
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
} else {
|
||||
for (int ch = 0; ch < channels; ch+=2) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>((sums[ch] - sums[ch+1]));
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
}
|
||||
partialBinSize = 0;
|
||||
LOGD("Partial bins are empty");
|
||||
|
||||
} else {
|
||||
// Not enough samples to complete the bin, update partialBin
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
partialBin[ch] = sums[ch];
|
||||
}
|
||||
partialBinSize += current_sample;
|
||||
LOGD("Partial bins were updated");
|
||||
return result_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill bins
|
||||
// ----
|
||||
LOGD("Fillin bins");
|
||||
for (int i = 0; i < bin_count; i++) {
|
||||
|
||||
LOGD("Current sample %d", current_sample);
|
||||
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] = p_source[current_sample * channels + ch]; // Initialize sums with first value in the input buffer
|
||||
}
|
||||
|
||||
for (int j = 1; j < binSize; j++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
sums[ch] += p_source[(current_sample + j) * channels + ch];
|
||||
}
|
||||
}
|
||||
current_sample += binSize;
|
||||
|
||||
// Finish binning, then subtact two channel and store the result
|
||||
if (average) {
|
||||
for (int ch = 0; ch < channels; ch+=2) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>((sums[ch]-sums[ch+1]) / binSize);
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
} else {
|
||||
for (int ch = 0; ch < channels; ch+=2) {
|
||||
p_target[result_size / sizeof(T)] = static_cast<T>((sums[ch]-sums[ch+1]));
|
||||
result_size += sizeof(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the remaining samples in the partial bin
|
||||
// ----
|
||||
LOGD("Updating partial bins");
|
||||
for (int i = 0; i < remaining_samples; i++) {
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
partialBin[ch] += p_source[(current_sample + i) * channels + ch];
|
||||
}
|
||||
}
|
||||
partialBinSize = remaining_samples;
|
||||
|
||||
return result_size;
|
||||
}
|
||||
|
||||
protected:
|
||||
int channels = 2;
|
||||
int binSize = 4;
|
||||
bool average = true;
|
||||
T *partialBin;
|
||||
int partialBinSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Provides combination of binning and subtracting channels
|
||||
* @author Urs Utzinger
|
||||
* @ingroup convert
|
||||
* @tparam T
|
||||
*/
|
||||
|
||||
class ChannelBinDiff : public BaseConverter {
|
||||
public:
|
||||
ChannelBinDiff() = default;
|
||||
ChannelBinDiff(int binSize, int channels, bool average, int bits_per_sample) {
|
||||
setChannels(channels);
|
||||
setBinSize(binSize);
|
||||
setAverage(average);
|
||||
setBits(bits_per_sample);
|
||||
}
|
||||
|
||||
void setChannels(int channels) {
|
||||
assert((channels % 2) == 0); // Ensure even channel size
|
||||
this->channels = channels;
|
||||
}
|
||||
void setBits(int bits) { this->bits = bits; }
|
||||
void setBinSize(int binSize) { this->binSize = binSize; }
|
||||
void setAverage(bool average) { this->average = average; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
|
||||
size_t convert(uint8_t *target, uint8_t *src, size_t size) {
|
||||
switch (bits) {
|
||||
case 8: {
|
||||
ChannelBinDiffT<int8_t> bd8(binSize, channels, average);
|
||||
return bd8.convert(target, src, size);
|
||||
}
|
||||
case 16: {
|
||||
ChannelBinDiffT<int16_t> bd16(binSize, channels, average);
|
||||
return bd16.convert(target, src, size);
|
||||
}
|
||||
case 24: {
|
||||
ChannelBinDiffT<int24_t> bd24(binSize, channels, average);
|
||||
return bd24.convert(target, src, size);
|
||||
}
|
||||
case 32: {
|
||||
ChannelBinDiffT<int32_t> bd32(binSize, channels, average);
|
||||
return bd32.convert(target, src, size);
|
||||
}
|
||||
default: {
|
||||
LOGE("Number of bits %d not supported.", bits);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int channels = 2;
|
||||
int bits = 16;
|
||||
int binSize = 4;
|
||||
bool average = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Increases the channel count
|
||||
* @ingroup convert
|
||||
@ -1018,7 +1465,7 @@ class Converter1Channel : public BaseConverter {
|
||||
public:
|
||||
Converter1Channel(Filter<T> &filter) { this->p_filter = &filter; }
|
||||
|
||||
size_t convert(uint8_t *src, size_t size) {
|
||||
size_t convert(uint8_t *src, size_t size) override {
|
||||
T *data = (T *)src;
|
||||
for (size_t j = 0; j < size; j++) {
|
||||
data[j] = p_filter->process(data[j]);
|
||||
|
20136
tests-cmake/codec/aac-faad/audio.h
Normal file
20136
tests-cmake/codec/aac-faad/audio.h
Normal file
File diff suppressed because it is too large
Load Diff
20136
tests-cmake/codec/aac-fdk/audio.h
Normal file
20136
tests-cmake/codec/aac-fdk/audio.h
Normal file
File diff suppressed because it is too large
Load Diff
20136
tests-cmake/codec/aac-helix/audio.h
Normal file
20136
tests-cmake/codec/aac-helix/audio.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user