diff --git a/CMakeLists.txt b/CMakeLists.txt index 522d8fc3..8547ab87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1053,21 +1053,6 @@ if (MINIAUDIO_BUILD_TOOLS) target_compile_definitions(miniaudio_cli PRIVATE MA_NO_THREADING) # We want to be able to test device I/O without threading. endif() - add_executable(audioconverter ${TOOLS_DIR}/audioconverter/audioconverter.c) - target_link_libraries(audioconverter PRIVATE ${COMMON_LINK_LIBRARIES}) - if (TARGET libvorbis_interface) - target_link_libraries(audioconverter PRIVATE libvorbis_interface) - else() - target_compile_definitions(audioconverter PRIVATE MA_NO_LIBVORBIS) - message(STATUS "miniaudio_libvorbis is disabled. Vorbis support is disabled in audioconverter.") - endif() - if (TARGET libopus_interface) - target_link_libraries(audioconverter PRIVATE libopus_interface) - else() - target_compile_definitions(audioconverter PRIVATE MA_NO_LIBOPUS) - message(STATUS "miniaudio_libopus is disabled. Opus support is disabled in audioconverter.") - endif() - add_executable(madoc ${TOOLS_DIR}/madoc/madoc.c) endif() diff --git a/tools/audioconverter/audioconverter.c b/tools/audioconverter/audioconverter.c deleted file mode 100644 index 8bf3baec..00000000 --- a/tools/audioconverter/audioconverter.c +++ /dev/null @@ -1,289 +0,0 @@ -/* -USAGE: audioconverter [input file] [output file] [format] [channels] [rate] - -EXAMPLES: - audioconverter my_file.flac my_file.wav - audioconverter my_file.flac my_file.wav f32 44100 linear --linear-order 8 -*/ -#define MA_NO_DEVICE_IO -#define MA_NO_THREADING -#define MINIAUDIO_IMPLEMENTATION -#include "../../miniaudio.h" -#include "../../extras/decoders/libvorbis/miniaudio_libvorbis.h" -#include "../../extras/decoders/libopus/miniaudio_libopus.h" - -#include - -void print_usage() -{ - printf("USAGE: audioconverter [input file] [output file] [format] [channels] [rate]\n"); - printf(" [format] is optional and can be one of the following:\n"); - printf(" u8 8-bit unsigned integer\n"); - printf(" s16 16-bit signed integer\n"); - printf(" s24 24-bit signed integer (tightly packed)\n"); - printf(" s32 32-bit signed integer\n"); - printf(" f32 32-bit floating point\n"); - printf(" [channels] is optional and in the range of %d and %d\n", MA_MIN_CHANNELS, MA_MAX_CHANNELS); - printf(" [rate] is optional and in the range of %d and %d\n", ma_standard_sample_rate_min, ma_standard_sample_rate_max); - printf("\n"); - printf("PARAMETERS:\n"); - printf(" --linear-order [0..%d]\n", MA_MAX_FILTER_ORDER); -} - -ma_result do_conversion(ma_decoder* pDecoder, ma_encoder* pEncoder) -{ - ma_result result = MA_SUCCESS; - - MA_ASSERT(pDecoder != NULL); - MA_ASSERT(pEncoder != NULL); - - /* - All we do is read from the decoder and then write straight to the encoder. All of the necessary data conversion - will happen internally. - */ - for (;;) { - ma_uint8 pRawData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; - ma_uint64 framesReadThisIteration; - ma_uint64 framesToReadThisIteration; - - framesToReadThisIteration = sizeof(pRawData) / ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels); - result = ma_decoder_read_pcm_frames(pDecoder, pRawData, framesToReadThisIteration, &framesReadThisIteration); - if (result != MA_SUCCESS) { - break; /* Reached the end, or an error occurred. */ - } - - /* At this point we have the raw data from the decoder. We now just need to write it to the encoder. */ - ma_encoder_write_pcm_frames(pEncoder, pRawData, framesReadThisIteration, NULL); - - /* Get out of the loop if we've reached the end. */ - if (framesReadThisIteration < framesToReadThisIteration) { - break; - } - } - - return result; -} - -ma_bool32 is_number(const char* str) -{ - if (str == NULL || str[0] == '\0') { - return MA_FALSE; - } - - while (str[0] != '\0') { - if (str[0] < '0' || str[0] > '9') { - return MA_FALSE; - } - - str += 1; - } - - return MA_TRUE; -} - -ma_bool32 try_parse_uint32_in_range(const char* str, ma_uint32* pValue, ma_uint32 lo, ma_uint32 hi) -{ - ma_uint32 x; - - if (!is_number(str)) { - return MA_FALSE; /* Not an integer. */ - } - - x = (ma_uint32)atoi(str); - if (x < lo || x > hi) { - return MA_FALSE; /* Out of range. */ - } - - if (pValue != NULL) { - *pValue = x; - } - - return MA_TRUE; -} - -ma_bool32 try_parse_format(const char* str, ma_format* pValue) -{ - ma_format format; - - /* */ if (strcmp(str, "u8") == 0) { - format = ma_format_u8; - } else if (strcmp(str, "s16") == 0) { - format = ma_format_s16; - } else if (strcmp(str, "s24") == 0) { - format = ma_format_s24; - } else if (strcmp(str, "s32") == 0) { - format = ma_format_s32; - } else if (strcmp(str, "f32") == 0) { - format = ma_format_f32; - } else { - return MA_FALSE; /* Not a format. */ - } - - if (pValue != NULL) { - *pValue = format; - } - - return MA_TRUE; -} - -ma_bool32 try_parse_channels(const char* str, ma_uint32* pValue) -{ - return try_parse_uint32_in_range(str, pValue, MA_MIN_CHANNELS, MA_MAX_CHANNELS); -} - -ma_bool32 try_parse_sample_rate(const char* str, ma_uint32* pValue) -{ - return try_parse_uint32_in_range(str, pValue, ma_standard_sample_rate_min, ma_standard_sample_rate_max); -} - -ma_bool32 try_parse_resample_algorithm(const char* str, ma_resample_algorithm* pValue) -{ - ma_resample_algorithm algorithm; - - /* */ if (strcmp(str, "linear") == 0) { - algorithm = ma_resample_algorithm_linear; - } else { - return MA_FALSE; /* Not a valid algorithm */ - } - - if (pValue != NULL) { - *pValue = algorithm; - } - - return MA_TRUE; -} - -int main(int argc, char** argv) -{ - ma_result result; - ma_decoder_config decoderConfig; - ma_decoder decoder; - ma_encoder_config encoderConfig; - ma_encoder encoder; - ma_encoding_format outputEncodingFormat; - ma_format format = ma_format_unknown; - ma_uint32 channels = 0; - ma_uint32 rate = 0; - ma_resample_algorithm resampleAlgorithm; - ma_uint32 linearOrder = 8; - int iarg; - const char* pOutputFilePath; - ma_decoding_backend_vtable* pDecodingBackends[] = - { - ma_decoding_backend_libvorbis, - ma_decoding_backend_libopus, - ma_decoding_backend_wav, - ma_decoding_backend_flac, - ma_decoding_backend_mp3 /* <-- MP3 seems to be worst/slowest at detecting whether or not it's a valid file so we'll put this last. */ - }; - - /* Print help if requested. */ - if (argc == 2) { - if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { - print_usage(); - return 0; - } - } - - if (argc < 3) { - print_usage(); - return -1; - } - - resampleAlgorithm = ma_resample_algorithm_linear; - - /* - The fourth and fifth arguments can be a format and/or rate specifier. It doesn't matter which order they are in as we can identify them by whether or - not it's a number. If it's a number we assume it's a sample rate, otherwise we assume it's a format specifier. - */ - for (iarg = 3; iarg < argc; iarg += 1) { - if (strcmp(argv[iarg], "--linear-order") == 0) { - iarg += 1; - if (iarg >= argc) { - break; - } - - if (!try_parse_uint32_in_range(argv[iarg], &linearOrder, 0, 8)) { - printf("Expecting a number between 0 and %d for --linear-order.\n", MA_MAX_FILTER_ORDER); - return -1; - } - - continue; - } - - if (try_parse_resample_algorithm(argv[iarg], &resampleAlgorithm)) { - continue; - } - - if (try_parse_format(argv[iarg], &format)) { - continue; - } - - if (try_parse_channels(argv[iarg], &channels)) { - continue; - } - - if (try_parse_sample_rate(argv[iarg], &rate)) { - continue; - } - - /* Getting here means we have an unknown parameter. */ - printf("Warning: Unknown parameter \"%s\"", argv[iarg]); - } - - /* Initialize a decoder for the input file. */ - decoderConfig = ma_decoder_config_init(format, channels, rate); - decoderConfig.ppBackendVTables = pDecodingBackends; - decoderConfig.backendCount = ma_countof(pDecodingBackends); - decoderConfig.resampling.algorithm = resampleAlgorithm; - decoderConfig.resampling.linear.lpfOrder = linearOrder; - - result = ma_decoder_init_file(argv[1], &decoderConfig, &decoder); - if (result != MA_SUCCESS) { - size_t iDecodingBackend; - printf("Failed to open input file. Check the file exists and the format is supported. Supported decoding backends:\n"); - - for (iDecodingBackend = 0; iDecodingBackend < ma_countof(pDecodingBackends); iDecodingBackend += 1) { - if (pDecodingBackends[iDecodingBackend] != NULL && pDecodingBackends[iDecodingBackend]->onInfo != NULL) { - ma_decoding_backend_info backendInfo; - pDecodingBackends[iDecodingBackend]->onInfo(NULL, &backendInfo); - printf(" %s (via %s)\n", backendInfo.pName, backendInfo.pLibraryName); - } - } - - return (int)result; - } - - - pOutputFilePath = argv[2]; - - outputEncodingFormat = ma_encoding_format_wav; /* Wave by default in case we don't know the file extension. */ - if (ma_path_extension_equal(pOutputFilePath, "wav")) { - outputEncodingFormat = ma_encoding_format_wav; - } else { - printf("Warning: Unknown file extension \"%s\". Encoding as WAV.\n", ma_path_extension(pOutputFilePath)); - } - - /* Initialize the encoder for the output file. */ - encoderConfig = ma_encoder_config_init(outputEncodingFormat, decoder.outputFormat, decoder.outputChannels, decoder.outputSampleRate); - result = ma_encoder_init_file(pOutputFilePath, &encoderConfig, &encoder); - if (result != MA_SUCCESS) { - ma_decoder_uninit(&decoder); - printf("Failed to open output file. Check that the directory exists and that the file is not already opened by another process. %s", ma_result_description(result)); - return -1; - } - - - /* We have our decoder and encoder ready, so now we can do the conversion. */ - result = do_conversion(&decoder, &encoder); - - - /* Done. */ - ma_encoder_uninit(&encoder); - ma_decoder_uninit(&decoder); - - return (int)result; -} - -#include "../../extras/decoders/libvorbis/miniaudio_libvorbis.c" -#include "../../extras/decoders/libopus/miniaudio_libopus.c"