/* audio: audio output interface copyright ?-2016 by the mpg123 project - free software under the terms of the LGPL 2.1 see COPYING and AUTHORS files in distribution or http://mpg123.org initially written by Michael Hipp */ #include #include "mpg123app.h" #include "audio.h" #include "out123.h" #include "common.h" #include "sysutil.h" #ifdef HAVE_SYS_WAIT_H #include #endif #include "debug.h" mpg123_string* audio_enclist(void) { int i; mpg123_string *list; size_t enc_count = 0; const int *enc_codes = NULL; /* Only the encodings supported by libmpg123 build Those returned by out123_enc_list() are a superset. */ mpg123_encodings(&enc_codes, &enc_count); if((list = malloc(sizeof(*list)))) mpg123_init_string(list); /* Further calls to mpg123 string lib are hardened against NULL. */ for(i=0;i0) mpg123_add_string(list, " "); mpg123_add_string(list, out123_enc_name(enc_codes[i])); } return list; } static void capline(mpg123_handle *mh, long rate) { int enci; const int *encs; size_t num_encs; mpg123_encodings(&encs, &num_encs); fprintf(stderr," %5ld |", pitch_rate(rate)); for(enci=0; enci 2) fprintf(stderr, "Note: forcing encoding code 0x%x (%s)\n" , force_fmt, out123_enc_name(force_fmt)); } /* Lots of preparation of rate lists. */ rlimit = param.force_rate > 0 ? num_rates+1 : num_rates; outrates = malloc(sizeof(*rates)*rlimit); unpitch = malloc(sizeof(*unpitch)*rlimit); if(!outrates || !unpitch) { if(!param.quiet) error("DOOM"); return; } for(ri = 0; ri 0) { int fi; int unpitch_i = 0; if(param.verbose > 1 && outfmts[0].encoding > 0) { const char *encname = out123_enc_name(outfmts[0].encoding); fprintf(stderr, "Note: default format %li Hz, %i channels, %s\n" , outfmts[0].rate, outfmts[0].channels , encname ? encname : "???" ); } for(fi=1; fi 2) fprintf( stderr , "Note: output support for %li Hz, %i channels: 0x%x\n" , outfmts[fi].rate, outfmts[fi].channels, outfmts[fi].encoding ); if(force_fmt) { /* Filter for forced encoding. */ if((fmts & force_fmt) == force_fmt) fmts = force_fmt; else /* Nothing else! */ fmts = 0; } mpg123_format( mh , brate(unpitch, outfmts[fi].rate, rlimit, &unpitch_i) , outfmts[fi].channels, fmts ); } } free(outfmts); free(unpitch); if(param.verbose > 1) print_capabilities(ao, mh); } int set_pitch(mpg123_handle *fr, out123_handle *ao, double new_pitch) { double old_pitch = param.pitch; long rate; int channels, format; int smode = 0; /* Be safe, check support. */ if(mpg123_getformat(fr, &rate, &channels, &format) != MPG123_OK) { /* We might just not have a track handy. */ error("There is no current audio format, cannot apply pitch. This might get fixed in future."); return 0; } param.pitch = new_pitch; if(param.pitch < -0.99) param.pitch = -0.99; if(channels == 1) smode = MPG123_MONO; if(channels == 2) smode = MPG123_STEREO; out123_stop(ao); /* Remember: This takes param.pitch into account. */ audio_capabilities(ao, fr); if(!(mpg123_format_support(fr, rate, format) & smode)) { /* Note: When using --pitch command line parameter, you can go higher because a lower decoder sample rate is automagically chosen. Here, we'd need to switch decoder rate during track... good? */ error("Reached a hardware limit there with pitch!"); param.pitch = old_pitch; audio_capabilities(ao, fr); } return out123_start(ao, pitch_rate(rate), channels, format); }