mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
187 lines
6.2 KiB
C
187 lines
6.2 KiB
C
#define DR_FLAC_IMPLEMENTATION
|
|
#include "../../extras/dr_flac.h" /* Enables FLAC decoding. */
|
|
#define DR_MP3_IMPLEMENTATION
|
|
#include "../../extras/dr_mp3.h" /* Enables MP3 decoding. */
|
|
#define DR_WAV_IMPLEMENTATION
|
|
#include "../../extras/dr_wav.h" /* Enables WAV decoding. */
|
|
|
|
|
|
#define MA_DEBUG_OUTPUT
|
|
#define MINIAUDIO_IMPLEMENTATION
|
|
#include "../../miniaudio.h"
|
|
#include "../ma_resampler.h"
|
|
|
|
#define USE_NEW_RESAMPLER 1
|
|
|
|
ma_uint64 g_outputFrameCount;
|
|
void* g_pRunningFrameData;
|
|
|
|
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
|
{
|
|
ma_uint32 framesToCopy;
|
|
|
|
framesToCopy = frameCount;
|
|
if (framesToCopy > (ma_uint32)g_outputFrameCount) {
|
|
framesToCopy = (ma_uint32)g_outputFrameCount;
|
|
}
|
|
|
|
MA_COPY_MEMORY(pOutput, g_pRunningFrameData, framesToCopy * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels));
|
|
|
|
g_pRunningFrameData = ma_offset_ptr(g_pRunningFrameData, framesToCopy * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels));
|
|
g_outputFrameCount -= framesToCopy;
|
|
|
|
(void)pInput;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
ma_result result;
|
|
ma_decoder_config decoderConfig;
|
|
ma_uint64 inputFrameCount;
|
|
void* pInputFrameData;
|
|
ma_uint64 outputFrameCount = 0;
|
|
void* pOutputFrameData = NULL;
|
|
ma_device_config deviceConfig;
|
|
ma_device device;
|
|
ma_backend backend;
|
|
|
|
/* This example just resamples the input file to an exclusive device's native sample rate. */
|
|
if (argc < 2) {
|
|
printf("No input file.\n");
|
|
return -1;
|
|
}
|
|
|
|
decoderConfig = ma_decoder_config_init(ma_format_f32, 1, 0);
|
|
|
|
result = ma_decode_file(argv[1], &decoderConfig, &inputFrameCount, &pInputFrameData);
|
|
if (result != MA_SUCCESS) {
|
|
return (int)result;
|
|
}
|
|
|
|
backend = ma_backend_wasapi;
|
|
|
|
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
|
#if USE_NEW_RESAMPLER
|
|
deviceConfig.playback.shareMode = ma_share_mode_exclusive; /* <-- We need to use exclusive mode to ensure there's no resampling going on by the OS. */
|
|
deviceConfig.sampleRate = 0; /* <-- Always use the device's native sample rate. */
|
|
#else
|
|
deviceConfig.playback.shareMode = ma_share_mode_shared; /* <-- We need to use exclusive mode to ensure there's no resampling going on by the OS. */
|
|
deviceConfig.sampleRate = decoderConfig.sampleRate;
|
|
#endif
|
|
deviceConfig.playback.format = decoderConfig.format;
|
|
deviceConfig.playback.channels = decoderConfig.channels;
|
|
deviceConfig.dataCallback = data_callback;
|
|
deviceConfig.pUserData = NULL;
|
|
|
|
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
|
printf("Failed to open playback device.\n");
|
|
ma_free(pInputFrameData);
|
|
return -3;
|
|
}
|
|
|
|
#if USE_NEW_RESAMPLER
|
|
/* Resample. */
|
|
outputFrameCount = ma_calculate_frame_count_after_src(device.sampleRate, decoderConfig.sampleRate, inputFrameCount);
|
|
pOutputFrameData = ma_malloc((size_t)(outputFrameCount * ma_get_bytes_per_frame(device.playback.format, device.playback.channels)));
|
|
if (pOutputFrameData == NULL) {
|
|
printf("Out of memory.\n");
|
|
ma_free(pInputFrameData);
|
|
ma_device_uninit(&device);
|
|
}
|
|
|
|
ma_resample_f32(ma_resample_algorithm_sinc, device.playback.internalSampleRate, decoderConfig.sampleRate, outputFrameCount, pOutputFrameData, inputFrameCount, pInputFrameData);
|
|
|
|
g_pRunningFrameData = pOutputFrameData;
|
|
g_outputFrameCount = outputFrameCount;
|
|
#else
|
|
g_pRunningFrameData = pInputFrameData;
|
|
g_outputFrameCount = inputFrameCount;
|
|
#endif
|
|
|
|
if (ma_device_start(&device) != MA_SUCCESS) {
|
|
printf("Failed to start playback device.\n");
|
|
ma_device_uninit(&device);
|
|
ma_free(pInputFrameData);
|
|
ma_free(pOutputFrameData);
|
|
return -4;
|
|
}
|
|
|
|
printf("Press Enter to quit...");
|
|
getchar();
|
|
|
|
ma_device_uninit(&device);
|
|
ma_free(pInputFrameData);
|
|
ma_free(pOutputFrameData);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
#define SAMPLE_RATE_IN 44100
|
|
#define SAMPLE_RATE_OUT 44100
|
|
#define CHANNELS 1
|
|
#define OUTPUT_FILE "output.wav"
|
|
|
|
ma_sine_wave sineWave;
|
|
|
|
ma_uint32 on_read(ma_resampler* pResampler, ma_uint32 frameCount, void** ppFramesOut)
|
|
{
|
|
ma_assert(pResampler->config.format == ma_format_f32);
|
|
|
|
return (ma_uint32)ma_sine_wave_read_f32_ex(&sineWave, frameCount, pResampler->config.channels, pResampler->config.layout, (float**)ppFramesOut);
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
ma_result result;
|
|
ma_resampler_config resamplerConfig;
|
|
ma_resampler resampler;
|
|
|
|
ma_zero_object(&resamplerConfig);
|
|
resamplerConfig.format = ma_format_f32;
|
|
resamplerConfig.channels = CHANNELS;
|
|
resamplerConfig.sampleRateIn = SAMPLE_RATE_IN;
|
|
resamplerConfig.sampleRateOut = SAMPLE_RATE_OUT;
|
|
resamplerConfig.algorithm = ma_resampler_algorithm_linear;
|
|
resamplerConfig.endOfInputMode = ma_resampler_end_of_input_mode_consume;
|
|
resamplerConfig.layout = ma_stream_layout_interleaved;
|
|
resamplerConfig.onRead = on_read;
|
|
resamplerConfig.pUserData = NULL;
|
|
|
|
result = ma_resampler_init(&resamplerConfig, &resampler);
|
|
if (result != MA_SUCCESS) {
|
|
printf("Failed to initialize resampler.\n");
|
|
return -1;
|
|
}
|
|
|
|
ma_sine_wave_init(0.5, 400, resamplerConfig.sampleRateIn, &sineWave);
|
|
|
|
|
|
// Write to a WAV file. We'll do about 10 seconds worth, making sure we read in chunks to make sure everything is seamless.
|
|
drwav_data_format format;
|
|
format.container = drwav_container_riff;
|
|
format.format = DR_WAVE_FORMAT_IEEE_FLOAT;
|
|
format.channels = resampler.config.channels;
|
|
format.sampleRate = resampler.config.sampleRateOut;
|
|
format.bitsPerSample = 32;
|
|
drwav* pWavWriter = drwav_open_file_write(OUTPUT_FILE, &format);
|
|
|
|
float buffer[SAMPLE_RATE_IN*CHANNELS];
|
|
float* pBuffer = buffer;
|
|
ma_uint32 iterations = 10;
|
|
ma_uint32 framesToReadPerIteration = ma_countof(buffer)/CHANNELS;
|
|
for (ma_uint32 i = 0; i < iterations; ++i) {
|
|
ma_uint32 framesRead = (ma_uint32)ma_resampler_read(&resampler, framesToReadPerIteration, &pBuffer);
|
|
drwav_write(pWavWriter, framesRead*CHANNELS, buffer);
|
|
}
|
|
|
|
//float** test = &buffer;
|
|
|
|
drwav_close(pWavWriter);
|
|
|
|
(void)argc;
|
|
(void)argv;
|
|
return 0;
|
|
}
|
|
#endif
|