Initial commit of mpg123-1.29.3

This commit is contained in:
Sam Lantinga
2022-05-07 15:47:18 -07:00
commit 01b6013145
352 changed files with 159933 additions and 0 deletions

62
doc/examples/Makefile Normal file
View File

@@ -0,0 +1,62 @@
targets = \
feedseek \
mpg123_to_out123 \
mpg123_to_wav_replaced_io \
scan \
id3dump \
mpglib \
dump_seekindex \
extract_frames
all: $(targets)
# On largefile-aware systems you might want to use these instead:
#MPG123_CFLAGS := $(shell pkg-config --cflags libmpg123_64)
#MPG123_LDFLAGS := $(shell pkg-config --libs libmpg123_64)
# This works on sane setups where off_t is off_t, and just that.
ifeq ($(MPG123_PREFIX),)
MPG123_CFLAGS := $(shell pkg-config --cflags libmpg123)
MPG123_LDFLAGS := $(shell pkg-config --libs libmpg123)
OUT123_CFLAGS := $(shell pkg-config --cflags libout123)
OUT123_LDFLAGS := $(shell pkg-config --libs libout123)
else # Yeah, that's with GNU/Linux in mind, at least GNU ld ...
MPG123_CFLAGS := -I$(MPG123_PREFIX)/include
MPG123_LDFLAGS := -L$(MPG123_PREFIX)/lib -Wl,-rpath $(MPG123_PREFIX)/lib -lmpg123
OUT123_CFLAGS := -I$(MPG123_PREFIX)/include
OUT123_LDFLAGS := -L$(MPG123_PREFIX)/lib -Wl,-rpath $(MPG123_PREFIX)/lib -lout123
endif
# Define to any C99 compiler.
CC = cc -std=c99
CFLAGS = -O
# Oder of libs not that important here...
compile = $(CC) $(CPPFLAGS) $(CFLAGS) $(MPG123_CFLAGS)
linkflags = $(MPG123_LDFLAGS) $(LDFLAGS)
mpg123_to_out123: mpg123_to_out123.c
$(compile) -o $@ $< $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags)
mpg123_to_wav_replaced_io: mpg123_to_wav_replaced_io.c
$(compile) -o $@ $< $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags)
feedseek: feedseek.c
$(compile) -o feedseek feedseek.c $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags)
scan: scan.c
$(compile) -o scan scan.c $(linkflags)
id3dump:id3dump.c
$(compile) -o id3dump id3dump.c $(linkflags)
dump_seekindex: dump_seekindex.c
$(compile) -o dump_seekindex dump_seekindex.c $(linkflags)
mpglib: mpglib.c
$(compile) -o mpglib mpglib.c $(linkflags)
extract_frames: extract_frames.c
$(compile) -o $@ $< $(linkflags)
clean:
rm -vf $(targets)

View File

@@ -0,0 +1,44 @@
/*
dump_seekindex: Scan a mpeg file and dump its seek index.
This is example code only sensible to be considered in the public domain.
Initially written by Patrick Dehne.
*/
#include <mpg123.h>
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char **argv)
{
mpg123_handle *m;
off_t* offsets;
off_t step;
size_t fill, i;
if(argc != 2)
{
fprintf(stderr, "\nI will dump the frame index of an MPEG audio file.\n");
fprintf(stderr, "\nUsage: %s <mpeg audio file>\n\n", argv[0]);
return -1;
}
#if MPG123_API_VERSION < 46
// Newer versions of the library don't need that anymore, but it is safe
// to have the no-op call present for compatibility with old versions.
mpg123_init();
#endif
m = mpg123_new(NULL, NULL);
mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0);
mpg123_param(m, MPG123_INDEX_SIZE, -1, 0);
mpg123_open(m, argv[1]);
mpg123_scan(m);
mpg123_index(m, &offsets, &step, &fill);
for(i=0; i<fill;i++) {
printf("Frame number %"PRIiMAX": file offset %"PRIiMAX"\n", (intmax_t)(i * step), (intmax_t)offsets[i]);
}
mpg123_close(m);
mpg123_delete(m);
return 0;
}

View File

@@ -0,0 +1,97 @@
/*
extract_frams: utlize the framebyframe API and mpg123_framedata to extract the MPEG frames out of a stream (strip off anything else).
This is example code only sensible to be considered in the public domain.
Initially written by Thomas Orgis.
*/
#include <mpg123.h>
/* unistd.h is not available under MSVC,
io.h defines the read and write functions */
#ifndef _MSC_VER
#include <unistd.h>
#else
#include <io.h>
#endif
#include <stdio.h>
#include <string.h>
/** The actual work on the existing handle. */
int do_work(mpg123_handle *m);
/** The main program. */
int main(int argc, char **argv)
{
int ret = 0;
mpg123_handle *m;
#if MPG123_API_VERSION < 46
// Newer versions of the library don't need that anymore, but it is safe
// to have the no-op call present for compatibility with old versions.
mpg123_init();
#endif
m = mpg123_new(NULL, &ret);
if(m == NULL)
{
fprintf(stderr, "Cannot create handle: %s", mpg123_plain_strerror(ret));
}
else
{
fprintf(stderr, "I'll take your dirty MPEG audio from standard input and will write the extracted pure MPEG data to standard output.\n");
if(argc > 1 && strcmp(argv[1], "--noinfo") == 0)
{
fprintf(stderr, "Enabling parsing/consuming of the Info frame so that it will not appear in output.\n");
ret = mpg123_param(m, MPG123_REMOVE_FLAGS, MPG123_IGNORE_INFOFRAME, 0.);
}
else
{
fprintf(stderr, "If you'd have given --noinfo as argument, I would omit a LAME/Xing info frame.\n");
ret = mpg123_param(m, MPG123_ADD_FLAGS, MPG123_IGNORE_INFOFRAME, 0.);
}
if(ret == 0) ret = do_work(m);
if(ret != 0) fprintf(stderr, "Some error occured: %s\n", mpg123_strerror(m));
mpg123_delete(m); /* Closes, too. */
}
return ret;
}
int do_work(mpg123_handle *m)
{
int ret;
size_t count = 0;
ret = mpg123_open_fd(m, STDIN_FILENO);
if(ret != MPG123_OK) return ret;
while( (ret = mpg123_framebyframe_next(m)) == MPG123_OK || ret == MPG123_NEW_FORMAT )
{
unsigned long header;
unsigned char *bodydata;
size_t bodybytes;
if(mpg123_framedata(m, &header, &bodydata, &bodybytes) == MPG123_OK)
{
/* Need to extract the 4 header bytes from the native storage in the correct order. */
unsigned char hbuf[4];
int i;
for(i=0; i<4; ++i) hbuf[i] = (unsigned char) ((header >> ((3-i)*8)) & 0xff);
/* Now write out both header and data, fire and forget. */
write(STDOUT_FILENO, hbuf, 4);
write(STDOUT_FILENO, bodydata, bodybytes);
fprintf(stderr, "%zu: header 0x%08lx, %zu body bytes\n", ++count, header, bodybytes);
}
}
if(ret != MPG123_DONE)
fprintf(stderr, "Some error occured (non-fatal?): %s\n", mpg123_strerror(m));
fprintf(stderr, "Done with %zu MPEG frames.\n", count);
return 0;
}

164
doc/examples/feedseek.c Normal file
View File

@@ -0,0 +1,164 @@
/*
feedseek: test program for libmpg123, showing how to use fuzzy seeking in feeder mode
This is example code only sensible to be considered in the public domain.
It takes MPEG data from standard input and feeds that to libmpg123, combined
with a fuzzy seek. Libmpg123 could access stdin in other ways directly, but
usage of the feeder API is the point here.
*/
#define _POSIX_C_SOURCE 200112L /**< POSIX standard for ftello. */
#include <mpg123.h>
#include <out123.h>
#include <stdlib.h>
#include <stdio.h>
#define INBUFF 16384 * 2 * 2 /**< input buffer size */
/** Error handling helper, end program if condition is not met.
* Yes, a goto for error handling. Controlled cleanup in a final section instead
* of just jumping out of the program.
*/
#define CHECK(cond, ...) if(!(cond)){ fprintf(stderr, __VA_ARGS__); goto bad_end; }
/** The whole operation. */
int main(int argc, char **argv)
{
unsigned char buf[INBUFF];
mpg123_handle *m = NULL;
out123_handle *o = NULL;
const char *driver = NULL;
char *device = NULL;
int ret = 0;
off_t inoffset;
off_t cur_inoffset;
off_t seek_point = 0;
off_t seek_target;
// 0. Argument parsing.
if(argc < 2)
{
fprintf(stderr, "Usage:\n\n %s <offset> [outfile] < <MPEG input data>\n", argv[0]);
fprintf( stderr, "\n"
"This will decode standard input to the default audio device or the\n"
"given output file as decoded WAV after seeking to the given PCM sample\n"
"offset to demonstrate fuzzy seeking\n" );
return 1;
}
seek_point = atol(argv[1]);
CHECK(seek_point >= 0, "No negative offset, please.\n")
if(argc >= 3)
{
driver = "wav";
device = argv[2];
}
// 1. Initialize libmpg123 and libout123 handles.
#if MPG123_API_VERSION < 46
// Newer versions of the library don't need that anymore, but it is safe
// to have the no-op call present for compatibility with old versions.
mpg123_init();
#endif
m = mpg123_new(NULL, &ret);
CHECK(m != NULL, "Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret))
o = out123_new();
CHECK(o != NULL, "Unable to create out123 handle.\n")
ret = out123_open(o, driver, device);
CHECK(ret == OUT123_OK, "Failed to open output device: %s\n", out123_strerror(o))
mpg123_param(m, MPG123_VERBOSE, 2, 0);
mpg123_param(m, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0);
CHECK(ret == MPG123_OK, "Unable to set library options: %s\n", mpg123_plain_strerror(ret))
// 2. Open the feeder, feed data until libmpg123 can tell us where to go in the input
// for the desired output offset.
ret = mpg123_open_feed(m);
CHECK(ret == MPG123_OK, "Unable open feed: %s\n", mpg123_plain_strerror(ret))
fprintf(stderr, "\nDetermining input offset for seek ...\n");
/* That condition is tricky... parentheses are crucial... */
while( (seek_target = mpg123_feedseek(m, seek_point, SEEK_SET, &inoffset))
== MPG123_NEED_MORE )
{
fprintf(stderr, " *** need more data before deciding on fuzzy input offset ***\n");
size_t len = fread(buf, 1, INBUFF, stdin);
if(len < 0 || (len == 0 && (feof(stdin) || ferror(stdin))))
break;
ret = mpg123_feed(m, buf, len);
CHECK(ret == MPG123_OK, "Error feeding the decoder: %s", mpg123_strerror(m))
}
CHECK(ret == MPG123_OK, "Feedseek failed: %s\n", mpg123_strerror(m))
fprintf( stderr, "Fuzzy seek to %lld, actually to %lld.\n"
, (long long)seek_point, (long long)seek_target );
CHECK(inoffset >=0 , "Bogus input offset: %lld\n", (long long)inoffset)
// 3. Go to the indicated input offset.
fprintf(stderr, "\nSeeking to input offset ...\n");
// In a normal file, we would call fseek() here, for stdin, we just consume data.
while( (cur_inoffset=ftello(stdin)) < inoffset && !ferror(stdin) )
{
CHECK(cur_inoffset >= 0, "Cannot tell input position.\n")
off_t block = inoffset - cur_inoffset;
if(block > INBUFF)
block = INBUFF;
if(fread(buf, 1, block, stdin) == 0 && feof(stdin))
break;
}
CHECK( ftello(stdin) == inoffset, "Input seeking failed: %lld != %lld\n"
, (long long)ftello(stdin), (long long)inoffset )
// 4. Feed the decoder from that point on and get the decoded audio.
fprintf(stderr, "\nStarting decode...\n");
while(1)
{
size_t len = fread(buf, sizeof(unsigned char), INBUFF, stdin);
if(len <= 0)
break;
ret = mpg123_feed(m, buf, len);
while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
{
off_t num;
unsigned char *audio;
size_t bytes;
ret = mpg123_decode_frame(m, &num, &audio, &bytes);
if(ret == MPG123_NEW_FORMAT)
{
long rate;
int channels, enc;
mpg123_getformat(m, &rate, &channels, &enc);
fprintf(stderr
, "New format: %li Hz, %i channels, encoding value %i\n"
, rate, channels, enc );
ret = out123_start(o, rate, channels, enc);
CHECK(ret == OUT123_OK, "Cannot (re)start audio output with given format.\n")
}
CHECK(out123_play(o, audio, bytes) == bytes, "Output error: %s", out123_strerror(o))
}
CHECK(ret != MPG123_ERR, "Error: %s", mpg123_strerror(m))
}
fprintf(stderr, "Finished\n");
good_end: // Everything went fine: go directly to the cleanup section.
goto end;
bad_end: // Some unspecified error, set error state and clean up.
ret = -1;
end: // Clean up and return.
out123_del(o);
mpg123_delete(m);
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
}

181
doc/examples/id3dump.c Normal file
View File

@@ -0,0 +1,181 @@
/*
id3dump: Print ID3 tags of files, scanned using libmpg123.
This is example code only sensible to be considered in the public domain.
Initially written by Thomas Orgis.
*/
#include "mpg123.h"
#include <string.h>
#include "stdio.h"
#include "sys/types.h"
/** Helper for v1 printing, get these strings their zero byte. */
void safe_print(char* name, char *data, size_t size)
{
char safe[31];
if(size>30) return;
memcpy(safe, data, size);
safe[size] = 0;
printf("%s: %s\n", name, safe);
}
/** Print out ID3v1 info. */
void print_v1(mpg123_id3v1 *v1)
{
safe_print("Title", v1->title, sizeof(v1->title));
safe_print("Artist", v1->artist, sizeof(v1->artist));
safe_print("Album", v1->album, sizeof(v1->album));
safe_print("Year", v1->year, sizeof(v1->year));
safe_print("Comment", v1->comment, sizeof(v1->comment));
printf("Genre: %i", v1->genre);
}
/** Split up a number of lines separated by \\n, \\r, both or just zero byte
and print out each line with specified prefix. */
void print_lines(const char* prefix, mpg123_string *inlines)
{
size_t i;
int hadcr = 0, hadlf = 0;
char *lines = NULL;
char *line = NULL;
size_t len = 0;
if(inlines != NULL && inlines->fill)
{
lines = inlines->p;
len = inlines->fill;
}
else return;
line = lines;
for(i=0; i<len; ++i)
{
if(lines[i] == '\n' || lines[i] == '\r' || lines[i] == 0)
{
char save = lines[i]; /* saving, changing, restoring a byte in the data */
if(save == '\n') ++hadlf;
if(save == '\r') ++hadcr;
if((hadcr || hadlf) && hadlf % 2 == 0 && hadcr % 2 == 0) line = "";
if(line)
{
lines[i] = 0;
printf("%s%s\n", prefix, line);
line = NULL;
lines[i] = save;
}
}
else
{
hadlf = hadcr = 0;
if(line == NULL) line = lines+i;
}
}
}
/** Print out the named ID3v2 fields. */
void print_v2(mpg123_id3v2 *v2)
{
print_lines("Title: ", v2->title);
print_lines("Artist: ", v2->artist);
print_lines("Album: ", v2->album);
print_lines("Year: ", v2->year);
print_lines("Comment: ", v2->comment);
print_lines("Genre: ", v2->genre);
}
/** Print out all stored ID3v2 fields with their 4-character IDs. */
void print_raw_v2(mpg123_id3v2 *v2)
{
size_t i;
for(i=0; i<v2->texts; ++i)
{
char id[5];
char lang[4];
memcpy(id, v2->text[i].id, 4);
id[4] = 0;
memcpy(lang, v2->text[i].lang, 3);
lang[3] = 0;
if(v2->text[i].description.fill)
printf("%s language(%s) description(%s)\n", id, lang, v2->text[i].description.p);
else printf("%s language(%s)\n", id, lang);
print_lines(" ", &v2->text[i].text);
}
for(i=0; i<v2->extras; ++i)
{
char id[5];
memcpy(id, v2->extra[i].id, 4);
id[4] = 0;
printf( "%s description(%s)\n",
id,
v2->extra[i].description.fill ? v2->extra[i].description.p : "" );
print_lines(" ", &v2->extra[i].text);
}
for(i=0; i<v2->comments; ++i)
{
char id[5];
char lang[4];
memcpy(id, v2->comment_list[i].id, 4);
id[4] = 0;
memcpy(lang, v2->comment_list[i].lang, 3);
lang[3] = 0;
printf( "%s description(%s) language(%s): \n",
id,
v2->comment_list[i].description.fill ? v2->comment_list[i].description.p : "",
lang );
print_lines(" ", &v2->comment_list[i].text);
}
}
/** The whole operation. */
int main(int argc, char **argv)
{
int i;
mpg123_handle* m;
if(argc < 2)
{
fprintf(stderr, "\nI will print some ID3 tag fields of MPEG audio files.\n");
fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]);
return -1;
}
#if MPG123_API_VERSION < 46
// Newer versions of the library don't need that anymore, but it is safe
// to have the no-op call present for compatibility with old versions.
mpg123_init();
#endif
m = mpg123_new(NULL, NULL);
for(i=1; i < argc; ++i)
{
mpg123_id3v1 *v1;
mpg123_id3v2 *v2;
int meta;
if(mpg123_open(m, argv[i]) != MPG123_OK)
{
fprintf(stderr, "Cannot open %s: %s\n", argv[i], mpg123_strerror(m));
continue;
}
mpg123_scan(m);
meta = mpg123_meta_check(m);
if(meta & MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK)
{
printf("Tag data on %s:\n", argv[i]);
printf("\n==== ID3v1 ====\n");
if(v1 != NULL) print_v1(v1);
printf("\n==== ID3v2 ====\n");
if(v2 != NULL) print_v2(v2);
printf("\n==== ID3v2 Raw frames ====\n");
if(v2 != NULL) print_raw_v2(v2);
}
else printf("Nothing found for %s.\n", argv[i]);
mpg123_close(m);
}
mpg123_delete(m);
return 0;
}

View File

@@ -0,0 +1,169 @@
/*
mpg123_to_wav.c
This is example code only sensible to be considered in the public domain.
Initially written by Nicholas Humfrey.
The most complicated part is about the choices to make about output format,
and prepare for the unlikely case a bastard mp3 might file change it.
*/
#include <out123.h>
#include <mpg123.h>
#include <stdio.h>
#include <strings.h>
/** Print usage info. */
void usage(const char *cmd)
{
printf("Usage: %s <input> [<driver> [<output> [encoding [buffersize]]]]\n"
, cmd);
printf( "\nPlay MPEG audio from intput file to output file/device using\n"
"specified out123 driver, sample encoding and buffer size optional.\n\n" );
exit(99);
}
/** Free handles. */
void cleanup(mpg123_handle *mh, out123_handle *ao)
{
out123_del(ao);
/* It's really to late for error checks here;-) */
mpg123_close(mh);
mpg123_delete(mh);
}
/** The whole operation. */
int main(int argc, char *argv[])
{
mpg123_handle *mh = NULL;
out123_handle *ao = NULL;
char *infile = NULL;
char *driver = NULL;
char *outfile = NULL;
unsigned char* buffer = NULL;
const char *encname;
size_t buffer_size = 0;
size_t done = 0;
int channels = 0;
int encoding = 0;
int framesize = 1;
long rate = 0;
int err = MPG123_OK;
off_t samples = 0;
if(argc<2)
usage(argv[0]);
infile = argv[1];
if(argc >= 3)
driver = argv[2];
if(argc >= 4)
outfile = argv[3];
printf("Input file: %s\n", infile);
printf("Output driver: %s\n", driver ? driver : "<nil> (default)");
printf("Output file: %s\n", outfile ? outfile : "<nil> (default)");
#if MPG123_API_VERSION < 46
// Newer versions of the library don't need that anymore, but it is safe
// to have the no-op call present for compatibility with old versions.
err = mpg123_init();
#endif
if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL)
{
fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
cleanup(mh, ao);
return -1;
}
ao = out123_new();
if(!ao)
{
fprintf(stderr, "Cannot create output handle.\n");
cleanup(mh, ao);
return -1;
}
if(argc >= 5)
{ /* Make mpg123 support the desired encoding only for all rates. */
const long *rates;
size_t rate_count;
size_t i;
int enc;
/* If that is zero, you'll get the error soon enough from mpg123. */
enc = out123_enc_byname(argv[4]);
mpg123_format_none(mh);
mpg123_rates(&rates, &rate_count);
for(i=0; i<rate_count; ++i)
mpg123_format(mh, rates[i], MPG123_MONO|MPG123_STEREO, enc);
}
/* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */
if( mpg123_open(mh, infile) != MPG123_OK
/* Peek into track and get first output format. */
|| mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK )
{
fprintf( stderr, "Trouble with mpg123: %s\n", mpg123_strerror(mh) );
cleanup(mh, ao);
return -1;
}
if(out123_open(ao, driver, outfile) != OUT123_OK)
{
fprintf(stderr, "Trouble with out123: %s\n", out123_strerror(ao));
cleanup(mh, ao);
return -1;
}
/* It makes no sense for that to give an error now. */
out123_driver_info(ao, &driver, &outfile);
printf("Effective output driver: %s\n", driver ? driver : "<nil> (default)");
printf("Effective output file: %s\n", outfile ? outfile : "<nil> (default)");
/* Ensure that this output format will not change
(it might, when we allow it). */
mpg123_format_none(mh);
mpg123_format(mh, rate, channels, encoding);
encname = out123_enc_name(encoding);
printf( "Playing with %i channels and %li Hz, encoding %s.\n"
, channels, rate, encname ? encname : "???" );
if( out123_start(ao, rate, channels, encoding)
|| out123_getformat(ao, NULL, NULL, NULL, &framesize) )
{
fprintf(stderr, "Cannot start output / get framesize: %s\n"
, out123_strerror(ao));
cleanup(mh, ao);
return -1;
}
/* Buffer could be almost any size here, mpg123_outblock() is just some
recommendation. The size should be a multiple of the PCM frame size. */
buffer_size = argc >= 6 ? atol(argv[5]) : mpg123_outblock(mh);
buffer = malloc( buffer_size );
do
{
size_t played;
err = mpg123_read( mh, buffer, buffer_size, &done );
played = out123_play(ao, buffer, done);
if(played != done)
{
fprintf(stderr
, "Warning: written less than gotten from libmpg123: %li != %li\n"
, (long)played, (long)done);
}
samples += played/framesize;
/* We are not in feeder mode, so MPG123_OK, MPG123_ERR and
MPG123_NEW_FORMAT are the only possibilities.
We do not handle a new format, MPG123_DONE is the end... so
abort on anything not MPG123_OK. */
} while (done && err==MPG123_OK);
free(buffer);
if(err != MPG123_DONE)
fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n",
err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) );
printf("%li samples written.\n", (long)samples);
cleanup(mh, ao);
return 0;
}

97
doc/examples/mpglib.c Normal file
View File

@@ -0,0 +1,97 @@
/*
mpglib: test program for libmpg123, in the style of the legacy mpglib test program
This is example code only sensible to be considered in the public domain.
Initially written by Thomas Orgis.
*/
#include <mpg123.h>
/* unistd.h is not available under MSVC,
io.h defines the read and write functions */
#ifndef _MSC_VER
#include <unistd.h>
#else
#include <io.h>
#endif
#ifdef _WIN32
#include <fcntl.h>
#endif
#include <stdio.h>
#define INBUFF 16384 /**< input buffer size */
#define OUTBUFF 32768 /**< output buffer size */
/** The whole operation. */
int main(int argc, char **argv)
{
size_t size;
unsigned char buf[INBUFF]; /* input buffer */
unsigned char out[OUTBUFF]; /* output buffer */
ssize_t len;
int ret;
size_t in = 0, outc = 0;
mpg123_handle *m;
#ifdef _WIN32
_setmode(_fileno(stdin),_O_BINARY);
_setmode(_fileno(stdout),_O_BINARY);
#endif
#if MPG123_API_VERSION < 46
// Newer versions of the library don't need that anymore, but it is safe
// to have the no-op call present for compatibility with old versions.
mpg123_init();
#endif
m = mpg123_new(argc > 1 ? argv[1] : NULL, &ret);
if(m == NULL)
{
fprintf(stderr,"Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret));
return -1;
}
mpg123_param(m, MPG123_VERBOSE, 2, 0); /* Brabble a bit about the parsing/decoding. */
/* Now mpg123 is being prepared for feeding. The main loop will read chunks from stdin and feed them to mpg123;
then take decoded data as available to write to stdout. */
mpg123_open_feed(m);
if(m == NULL) return -1;
fprintf(stderr, "Feed me some MPEG audio to stdin, I will decode to stdout.\n");
while(1) /* Read and write until everything is through. */
{
len = read(0,buf,INBUFF);
if(len <= 0)
{
fprintf(stderr, "input data end\n");
break;
}
in += len;
/* Feed input chunk and get first chunk of decoded audio. */
ret = mpg123_decode(m,buf,len,out,OUTBUFF,&size);
if(ret == MPG123_NEW_FORMAT)
{
long rate;
int channels, enc;
mpg123_getformat(m, &rate, &channels, &enc);
fprintf(stderr, "New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
}
if(write(1,out,size) != size)
fprintf(stderr, "Output truncated.\n");
outc += size;
while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
{ /* Get all decoded audio that is available now before feeding more input. */
ret = mpg123_decode(m,NULL,0,out,OUTBUFF,&size);
if(write(1,out,size) != size)
fprintf(stderr, "Output truncated.\n");
outc += size;
}
if(ret == MPG123_ERR){ fprintf(stderr, "some error: %s", mpg123_strerror(m)); break; }
}
fprintf(stderr, "%lu bytes in, %lu bytes out\n", (unsigned long)in, (unsigned long)outc);
/* Done decoding, now just clean up and leave. */
mpg123_delete(m);
return 0;
}

48
doc/examples/scan.c Normal file
View File

@@ -0,0 +1,48 @@
/*
scan: Estimate length (sample count) of a mpeg file and compare to length from exact scan.
This is example code only sensible to be considered in the public domain.
Initially written by Thomas Orgis
*/
/* Note the lack of error checking here.
While it would be nicer to inform the user about troubles, libmpg123 is designed _not_ to bite you on operations with invalid handles , etc.
You just jet invalid results on invalid operations... */
#include <mpg123.h>
#include <stdio.h>
/** The whole operation. */
int main(int argc, char **argv)
{
mpg123_handle *m;
int i;
if(argc < 2)
{
fprintf(stderr, "\nI will give you the estimated and exact sample lengths of MPEG audio files.\n");
fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]);
return -1;
}
#if MPG123_API_VERSION < 46
mpg123_init();
#endif
m = mpg123_new(NULL, NULL);
mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0); /* New in library version 0.0.1 . */
for(i = 1; i < argc; ++i)
{
off_t a, b;
mpg123_open(m, argv[i]);
a = mpg123_length(m);
mpg123_scan(m);
b = mpg123_length(m);
mpg123_close(m);
printf("File %i: estimated %li vs. scanned %li\n", i, (long)a, (long)b);
}
mpg123_delete(m);
return 0;
}