decoding to 32 bit
This commit is contained in:
@@ -8,12 +8,14 @@
|
||||
#define fprintf fprintf_s
|
||||
#endif
|
||||
|
||||
static void write_u16_le(FILE *f, uint16_t v) {
|
||||
static void write_u16_le(FILE *f, uint16_t v)
|
||||
{
|
||||
fputc((int)(v & 0xff), f);
|
||||
fputc((int)((v >> 8) & 0xff), f);
|
||||
}
|
||||
|
||||
static void write_u32_le(FILE *f, uint32_t v) {
|
||||
static void write_u32_le(FILE *f, uint32_t v)
|
||||
{
|
||||
fputc((int)(v & 0xff), f);
|
||||
fputc((int)((v >> 8) & 0xff), f);
|
||||
fputc((int)((v >> 16) & 0xff), f);
|
||||
@@ -24,7 +26,8 @@ static int write_wav_header(FILE *f,
|
||||
int sample_rate,
|
||||
int channels,
|
||||
int bits_per_sample,
|
||||
uint32_t data_size) {
|
||||
uint32_t data_size)
|
||||
{
|
||||
const uint32_t byte_rate =
|
||||
(uint32_t)(sample_rate * channels * bits_per_sample / 8);
|
||||
const uint16_t block_align =
|
||||
@@ -36,7 +39,7 @@ static int write_wav_header(FILE *f,
|
||||
|
||||
fwrite("fmt ", 1, 4, f);
|
||||
write_u32_le(f, 16); /* fmt chunk size */
|
||||
write_u16_le(f, 1); /* 1 = integer PCM */
|
||||
write_u16_le(f, 1); /* PCM */
|
||||
write_u16_le(f, (uint16_t)channels);
|
||||
write_u32_le(f, (uint32_t)sample_rate);
|
||||
write_u32_le(f, byte_rate);
|
||||
@@ -53,7 +56,8 @@ static int rewrite_wav_header(FILE *f,
|
||||
int sample_rate,
|
||||
int channels,
|
||||
int bits_per_sample,
|
||||
uint32_t data_size) {
|
||||
uint32_t data_size)
|
||||
{
|
||||
if (fseek(f, 0, SEEK_SET) != 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -65,37 +69,24 @@ static int rewrite_wav_header(FILE *f,
|
||||
data_size);
|
||||
}
|
||||
|
||||
static int write_decoder_buffer(FILE *out,
|
||||
fmpg_decoder *dec,
|
||||
uint64_t *total_written) {
|
||||
const uint8_t *buf = fmpg_decoder_buffer(dec);
|
||||
const int size = fmpg_decoder_buffer_size(dec);
|
||||
|
||||
if (!buf || size <= 0) {
|
||||
return 1;
|
||||
static void print_if_present(const char *label, const char *value)
|
||||
{
|
||||
if (value && value[0]) {
|
||||
printf("%s: %s\n", label, value);
|
||||
}
|
||||
|
||||
if (fwrite(buf, 1, (size_t)size, out) != (size_t)size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*total_written += (uint64_t)size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *infile;
|
||||
const char *outfile;
|
||||
|
||||
fmpg_instance *ac = NULL;
|
||||
fmpg_decoder *dec = NULL;
|
||||
fmpg_instance *fmpg = NULL;
|
||||
FILE *out = NULL;
|
||||
|
||||
int sample_rate;
|
||||
int channels;
|
||||
int bits_per_sample;
|
||||
int64_t duration_ms;
|
||||
int64_t duration_samples;
|
||||
uint64_t total_written = 0;
|
||||
|
||||
if (argc != 3) {
|
||||
@@ -106,48 +97,38 @@ int main(int argc, char **argv) {
|
||||
infile = argv[1];
|
||||
outfile = argv[2];
|
||||
|
||||
ac = fmpg_init();
|
||||
if (!ac) {
|
||||
fprintf(stderr, "ac_init failed\n");
|
||||
fmpg = fmpg_init();
|
||||
if (!fmpg) {
|
||||
fprintf(stderr, "fmpg_init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!fmpg_open_file(ac, infile)) {
|
||||
if (!fmpg_open_file(fmpg, infile)) {
|
||||
fprintf(stderr, "could not open input file: %s\n", infile);
|
||||
fmpg_free(ac);
|
||||
fmpg_free(fmpg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sample_rate = fmpg_audio_sample_rate(ac);
|
||||
channels = fmpg_audio_channels(ac);
|
||||
bits_per_sample = fmpg_audio_bits_per_sample(ac);
|
||||
duration_ms = fmpg_duration_ms(ac);
|
||||
duration_samples = fmpg_duration_samples(ac);
|
||||
sample_rate = fmpg_audio_sample_rate(fmpg);
|
||||
channels = fmpg_audio_channels(fmpg);
|
||||
bits_per_sample = fmpg_audio_bits_per_sample(fmpg);
|
||||
|
||||
if (sample_rate <= 0 || channels <= 0 || bits_per_sample != 32) {
|
||||
fprintf(stderr, "invalid audio parameters\n");
|
||||
fmpg_free(ac);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dec = fmpg_create_decoder(ac);
|
||||
if (!dec) {
|
||||
fprintf(stderr, "could not create decoder\n");
|
||||
fmpg_free(ac);
|
||||
fprintf(stderr, "unexpected audio format reported by decoder\n");
|
||||
fmpg_free(fmpg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out = fopen(outfile, "wb");
|
||||
if (!out) {
|
||||
fprintf(stderr, "could not open output file: %s\n", outfile);
|
||||
fmpg_free_decoder(dec);
|
||||
fmpg_free(ac);
|
||||
fmpg_free(fmpg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not know the final WAV data size yet.
|
||||
* Write a placeholder header first and patch it at the end.
|
||||
* The final WAV data size is only known after decoding. Write a temporary
|
||||
* header now and patch it after the decode loop.
|
||||
*/
|
||||
if (!write_wav_header(out,
|
||||
sample_rate,
|
||||
@@ -156,44 +137,22 @@ int main(int argc, char **argv) {
|
||||
0)) {
|
||||
fprintf(stderr, "could not write WAV header\n");
|
||||
fclose(out);
|
||||
fmpg_free_decoder(dec);
|
||||
fmpg_free(ac);
|
||||
fmpg_free(fmpg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
fmpg_package *pkg = fmpg_read_package(ac);
|
||||
while (fmpg_decode_next(fmpg)) {
|
||||
const uint8_t *buf = fmpg_buffer(fmpg);
|
||||
const int size = fmpg_buffer_size(fmpg);
|
||||
|
||||
if (!pkg) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* ac_read_package() now returns only packets from the internally
|
||||
* selected audio stream. No stream_index test is needed anymore.
|
||||
*/
|
||||
if (fmpg_decode_package(pkg, dec)) {
|
||||
if (!write_decoder_buffer(out, dec, &total_written)) {
|
||||
fprintf(stderr, "could not write PCM data\n");
|
||||
fmpg_free_package(pkg);
|
||||
if (buf && size > 0) {
|
||||
if (fwrite(buf, 1, (size_t)size, out) != (size_t)size) {
|
||||
fprintf(stderr, "write error\n");
|
||||
fclose(out);
|
||||
fmpg_free_decoder(dec);
|
||||
fmpg_free(ac);
|
||||
fmpg_free(fmpg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fmpg_free_package(pkg);
|
||||
}
|
||||
|
||||
/* Drain delayed samples from the decoder and resampler. */
|
||||
while (fmpg_flush_decoder(dec)) {
|
||||
if (!write_decoder_buffer(out, dec, &total_written)) {
|
||||
fprintf(stderr, "could not write flushed PCM data\n");
|
||||
fclose(out);
|
||||
fmpg_free_decoder(dec);
|
||||
fmpg_free(ac);
|
||||
return 1;
|
||||
total_written += (uint64_t)size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,24 +168,31 @@ int main(int argc, char **argv) {
|
||||
bits_per_sample,
|
||||
(uint32_t)total_written)) {
|
||||
fprintf(stderr, "could not rewrite WAV header\n");
|
||||
fclose(out);
|
||||
fmpg_free(fmpg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
|
||||
printf("wrote %s\n", outfile);
|
||||
printf("title: %s\n", fmpg_file_title(ac));
|
||||
printf("album: %s\n", fmpg_file_album(ac));
|
||||
printf("wrote: %s\n", outfile);
|
||||
printf("sample rate: %d\n", sample_rate);
|
||||
printf("channels: %d\n", channels);
|
||||
printf("sample bits: %d\n", bits_per_sample);
|
||||
printf("duration ms: %lld\n", (long long)duration_ms);
|
||||
printf("duration smp:%lld\n", (long long)duration_samples);
|
||||
printf("decoded smp: %lld\n", (long long)fmpg_decoder_sample_position(dec));
|
||||
printf("data bytes: %llu\n",
|
||||
(unsigned long long)total_written);
|
||||
printf("data bytes: %llu\n", (unsigned long long)total_written);
|
||||
printf("samples out: %lld\n", (long long)fmpg_sample_position(fmpg));
|
||||
|
||||
fmpg_free_decoder(dec);
|
||||
fmpg_free(ac);
|
||||
if (fmpg_duration_ms(fmpg) >= 0) {
|
||||
printf("duration ms: %lld\n", (long long)fmpg_duration_ms(fmpg));
|
||||
}
|
||||
if (fmpg_duration_samples(fmpg) >= 0) {
|
||||
printf("duration smp:%lld\n", (long long)fmpg_duration_samples(fmpg));
|
||||
}
|
||||
|
||||
print_if_present("title", fmpg_file_title(fmpg));
|
||||
print_if_present("artist", fmpg_file_author(fmpg));
|
||||
print_if_present("album", fmpg_file_album(fmpg));
|
||||
|
||||
fmpg_free(fmpg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user