/* CdL: Informatica Applicata Corso: Sistemi Multimediali Progetto: Sessione Invernale a.a. 2006/07 Sviluppatore: Andrea Nardi N.Matricola 216062 Professore: Andrea Acquaviva */ /************************************** * PROGRAMMA PER CODIFICA DA OGG A MP3 * ***************************************/ /********************** * INCLUSIONE LIBRERIE * **********************/ #include #include #include /************************************ * DICHIARAZIONE COSTANTI SIMBOLICHE * ************************************/ #define BSM 2000 /* banda segnale minima */ #define LSU 22050 /* limite superiore udibile */ #define LIU 0 /* limite inferiore udibile */ /* #define GST_FORMAT_PERCENT_MAX G_GINT64_CONSTANT (1000000) #define GST_FORMAT_PERCENT_SCALE G_GINT64_CONSTANT (10000) */ /********************************** * DICHIARAZIONE VARIABILI GLOBALI * **********************************/ GstElement *pipeline, *source, *oggparser, *oggmuxer, *oggdecoder, *conv, *low_filter, *high_filter, *conv2, *mp3encoder, *mp3decoder, *sink, *oggencoder; int band_control = 0; int glob_bsm = BSM; /* banda segnale minima */ int nullint = -1; double nulldbl = -1; /************************* * DICHIARAZIONE FUNZIONI * *************************/ int set_conv_params(int *, double *, int *, int *, int *, int *, int *, double *, double *); void wanna_change(char *); void set_filters(int *, int *); void yes_or_no(char *); void get_param_value(int *, double *, int, int); void band_check(int, int, double *, double *); /*********************** * DEFINIZIONE FUNZIONI * ***********************/ void yes_or_no(char *change) { /* dichiarazione variabili locali */ int sentinella; do { sentinella = 0; scanf("%s", change); if (strlen(change) >= 2) { printf("Invalid input lenght: insert only one character\n"); sentinella = -1; } else if (change[0] != 'y' && change[0] != 'n') sentinella = -1; } while (sentinella != 0); } void set_filters(int *lpf_on, int *hpf_on) { /* dichiarazione variabili locali */ char change[2]; printf("Do you want to activate a Low Pass Filter? (y/n) "); yes_or_no(change); if (change[0] == 'y') *lpf_on = 1; printf("Do you want to activate an High Pass Filter? (y/n) "); yes_or_no(change); if (change[0] == 'y') *hpf_on = 1; printf("Do you want to activate Band Control? (y/n) "); yes_or_no(change); if (change[0] == 'y') band_control = 1; } static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { /* dichiarazione variabili locali */ GMainLoop *loop = data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: { g_main_loop_quit (loop); g_print ("\rEnd-Of-Stream at: \n"); break; } case GST_MESSAGE_ERROR: { gchar *debug; GError *err; gst_message_parse_error (msg, &err, &debug); g_print ("Debug: %s\n", debug); g_free (debug); g_print ("Error: %s\n", err->message); g_error_free (err); g_main_loop_quit (loop); break; } default: break; } return TRUE; } static void new_pad_demux (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; /* We can now link this pad with the audio decoder */ g_print ("Dynamic pad created, linking demuxer/decoder\n"); sinkpad = gst_element_get_pad (oggdecoder, "sink"); gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); } static void new_pad_mux (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; /* We can now link this pad with the audio decoder */ g_print ("Dynamic pad created, linking encoder/muxer\n"); sinkpad = gst_element_get_pad (oggmuxer, "sink"); gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); } static gboolean cb_print_position (GstElement *pipeline) { /* dichiarazione variabili locali */ GstFormat fmt = GST_FORMAT_TIME; /* GstFormat perc = GST_FORMAT_BYTES; */ gint64 pos, len; if (gst_element_query_position (pipeline, &fmt, &pos) && gst_element_query_duration (pipeline, &fmt, &len)) { g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r", GST_TIME_ARGS (pos), GST_TIME_ARGS (len)); /* g_print ("Size: " " / " "\r", GST_TIME_ARGS (pos), GST_TIME_ARGS (len)); */ } /* call me again */ return TRUE; } int main (int argc, char *argv[]) { /* dichiarazione variabili locali */ GMainLoop *loop; GstBus *bus; /* GstQuery *query; gboolean res; */ int bitrate = 128, quality = 5, ch_mode = 4, br_mode = 0, lpf_on = 0, hpf_on = 0, create_err = 0, link_err = 0; double comp_ratio = 0, lpf_f = 440, hpf_f = 440; int scelta = 0; /* char mode_str[7], br_mode_str[5]; */ /* initialize GStreamer */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* check input arguments */ if (argc != 3) { g_print ("Usage: \n"); exit(EXIT_FAILURE); } /* stampa a video l'header del programma */ printf("********************************************\n"); printf("* PROGRAMMA PER CONVERSIONE TRA OGG ED MP3 *\n"); printf("********************************************\n"); printf("Conversion direction: 0 (OGG to MP3) - 1 (MP3 to OGG)\tDefault = 0\n"); get_param_value(&scelta, &nulldbl, 0, 1); set_filters(&lpf_on, &hpf_on); set_conv_params(&bitrate, &comp_ratio, &quality, &ch_mode, &br_mode, &lpf_on, &hpf_on, &lpf_f, &hpf_f); /* controllo banda minima garantita */ if (band_control) band_check(lpf_on, hpf_on, &lpf_f, &hpf_f); /* create elements */ pipeline = gst_pipeline_new ("converter"); source = gst_element_factory_make ("filesrc", "file-input"); conv = gst_element_factory_make ("audioconvert", "converter"); if (lpf_on) low_filter = gst_element_factory_make ("ladspa-lpf", "low-pass-filter"); if (hpf_on) high_filter = gst_element_factory_make ("ladspa-hpf", "high-pass-filter"); if (lpf_on || hpf_on) conv2 = gst_element_factory_make ("audioconvert", "converter2"); sink = gst_element_factory_make ("filesink", "file-output"); if (scelta == 0) { /* OGG to MP3 */ oggparser = gst_element_factory_make ("oggdemux", "ogg-parser"); oggdecoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder"); mp3encoder = gst_element_factory_make ("lame", "mp3encoder"); if (!oggparser || !oggdecoder || !mp3encoder) { create_err = 1; } } else { /* MP3 to OGG */ mp3decoder = gst_element_factory_make ("mad", "mp3-decoder"); oggencoder = gst_element_factory_make ("vorbisenc", "vorbis-encoder"); oggmuxer = gst_element_factory_make ("oggmux", "mp3-parser"); if (!oggmuxer || !mp3decoder || !oggencoder) { /* */ create_err = 1; } } if (!pipeline || !source || !conv || !sink) { create_err = 1; } if (lpf_on && !low_filter) { create_err = 2; } if (hpf_on && !high_filter) { create_err = 3; } if (lpf_on || hpf_on) if (!conv2) { create_err = 4; } if (create_err != 0) { g_print ("One element could not be created. (%d4)\n", create_err); printf ("Application will be terminated.\n"); exit(EXIT_FAILURE); } /* set filename property on the file source. Also add a message * handler. */ if (scelta == 0) { g_object_set (G_OBJECT (mp3encoder), "bitrate", bitrate, NULL); g_object_set (G_OBJECT (mp3encoder), "compression-ratio", comp_ratio, NULL); g_object_set (G_OBJECT (mp3encoder), "quality", quality, NULL); g_object_set (G_OBJECT (mp3encoder), "mode", ch_mode, NULL); g_object_set (G_OBJECT (mp3encoder), "vbr", br_mode, NULL); } if (lpf_on) g_object_set (G_OBJECT (low_filter), "Cutoff-Frequency", lpf_f, NULL); if (hpf_on) g_object_set (G_OBJECT (high_filter), "Cutoff-Frequency", hpf_f, NULL); g_object_set (G_OBJECT (source), "location", argv[1], NULL); g_object_set (G_OBJECT (sink), "location", argv[2], NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* put all elements in a bin */ gst_bin_add_many (GST_BIN (pipeline), source, conv, sink, NULL); if (scelta == 0) gst_bin_add_many (GST_BIN (pipeline), oggparser, oggdecoder, mp3encoder, NULL); else gst_bin_add_many (GST_BIN (pipeline), oggmuxer, mp3decoder, oggencoder, NULL); if (lpf_on) gst_bin_add(GST_BIN (pipeline), low_filter); if (hpf_on) gst_bin_add(GST_BIN (pipeline), high_filter); if (lpf_on || hpf_on) gst_bin_add(GST_BIN (pipeline), conv2); /* link together - note that we cannot link the parser and * decoder yet, becuse the parser uses dynamic pads. For that, * we set a pad-added signal handler. */ if (scelta == 0) g_signal_connect (oggparser, "pad-added", G_CALLBACK (new_pad_demux), NULL); else g_signal_connect (oggencoder, "pad-added", G_CALLBACK (new_pad_mux), NULL); if ((!gst_element_link(source, oggparser) && scelta == 0) || (!gst_element_link(oggencoder, oggmuxer) && scelta == 1)) { g_warning("Failed to link source/parser elements\n"); return -1; } if ((!gst_element_link(oggdecoder, conv) && scelta == 0) || (!gst_element_link(mp3decoder, conv) && scelta == 1)) { g_warning("Failed to link decoder/conv elements\n"); return -1; } if (lpf_on && hpf_on) { if ((!gst_element_link_many(conv, low_filter, high_filter, conv2, mp3encoder, sink, NULL) && scelta == 0) || (!gst_element_link_many(conv, low_filter, high_filter, conv2, oggencoder, oggmuxer, sink, NULL) && scelta == 1)) link_err = 1; } else if (lpf_on) { if ((!gst_element_link_many(conv, low_filter, conv2, mp3encoder, sink, NULL) && scelta == 0) || (!gst_element_link_many(conv, low_filter, conv2, oggencoder, oggmuxer, sink, NULL) && scelta == 1)) link_err = 2; } else if (hpf_on) { if ((!gst_element_link_many(conv, high_filter, conv2, mp3encoder, sink, NULL) && scelta == 0) || (!gst_element_link_many(conv, high_filter, conv2, oggencoder, oggmuxer, sink, NULL) && scelta == 1)) link_err = 3; } else { if ((!gst_element_link_many(conv, mp3encoder, sink, NULL) && scelta == 0) || (!gst_element_link_many(conv, oggencoder, oggmuxer, sink, NULL) && scelta == 1)) link_err = 4; } if (link_err != 0) { g_warning("Failed to link elements (step #%d)\n", link_err); printf ("Application will be terminated.\n"); exit(EXIT_FAILURE); } /* Now set to playing and iterate. */ g_print ("Setting to PLAYING\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); g_print ("Running\n"); g_timeout_add (200, (GSourceFunc) cb_print_position, pipeline); g_main_loop_run (loop); /* clean up nicely */ g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); return 0; } int set_conv_params(int *bitrate, double *comp_ratio, int *quality, int *ch_mode, int *br_mode, int *lpf_on, int *hpf_on, double *lpf_f, double *hpf_f) { /* dichiarazione variabili locali */ char change[2]; char *ch_mode_str[5] = {"Stereo", "Joint Stereo", "Dual Channel", "Mono", "Auto"}; char *br_mode_str[4] = {"Costant", "Old VBR", "Average VBR", "New VBR"}; int parameter, sent_bms = 0; wanna_change(change); do { if (change[0] == 'y' || sent_bms != 0) { printf("What parameter would you like to change?\n" "(1)\tBitRate (%d kbps / 320 kbps)\n" "(2)\tCompression Ratio (%.3f %% / 200 %%)\n" "(3)\tQuality (%d / 10)\n" "(4)\tChannel Mode (%s)\n" "(5)\tBitRate Mode (%s)\n" "(6)\tMinimum Signal Band (%d hz)\n", *bitrate, *comp_ratio, *quality, ch_mode_str[*ch_mode], br_mode_str[*br_mode], glob_bsm); if (*lpf_on) printf ("(%d)\tLow Pass Filter Cut-off Frequency (%.3f hz)\n", 6 + *lpf_on, *lpf_f); if (*hpf_on) printf ("(%d)\tHigh Pass Filter Cut-off Frequency (%.3f hz)\n", 6 + *lpf_on + *hpf_on, *hpf_f); printf("(%d)\tAbort\n", 6 + *lpf_on + *hpf_on + 1); get_param_value(¶meter, &nulldbl, 1, 6 + *lpf_on + *hpf_on + 1); if (parameter < 6 + *lpf_on + *hpf_on + 1) { if ((parameter >= 1) && (parameter <= 6)) { switch (parameter) { case 1: { printf("Range: 8 (Min) - 320 (Max) kbps\tDefault = 128\n"); get_param_value(bitrate, &nulldbl, 8, 320); break; } case 2: { printf("Range: 0 (Min) - 200 (Max)\tDefault = 0\n"); get_param_value(&nullint, comp_ratio, 0, 200); break; } case 3: { printf("Range: 0 (Best) - 9 (Worst)\tDefault = 5\n"); get_param_value(quality, &nulldbl, 0, 9); break; } case 4: { printf("Values: 0 = %s, 1 = %s, 2 = %s, 3 = %s, 4 = %s (Default)\n", ch_mode_str[0], ch_mode_str[1], ch_mode_str[2], ch_mode_str[3], ch_mode_str[4]); get_param_value(ch_mode, &nulldbl, 0, 4); break; } case 5: { printf("Values: 0 = %s (Default), 1 = %s, 2 = %s, 3 = %s\n", br_mode_str[0], br_mode_str[1], br_mode_str[2], br_mode_str[3]); get_param_value(br_mode, &nulldbl, 0, 3); break; } case 6: { printf("Actual Value: %d khz, (Default = %d khz)\n", glob_bsm, BSM); get_param_value(&glob_bsm, &nulldbl, LIU, LSU); break; } default: break; } } else if (parameter == 7 && *lpf_on) { printf("Range: %d - %d hz\tDefault = 440\n", LIU, LSU); get_param_value(&nullint, lpf_f, LIU, LSU); } else if (parameter == 8 || (parameter == 7 && !*lpf_on)) { printf("Range: %d - %d hz\tDefault = 440\n", LIU, LSU); get_param_value(&nullint, hpf_f, LIU, LSU); } else {}; } else printf("Operation aborted by user\n"); } if (change[0] == 'y') wanna_change(change); } while ((change[0] == 'y') || (sent_bms != 0)); return 0; } void get_param_value(int *valore, double *valore2, int min, int max) { /* dichiarazione variabili locali */ int sentinella; do { sentinella = 0; if (*valore2 == -1) { /* intero */ scanf(" %d", valore); if (!(*valore >= min && *valore <= max)) sentinella = -1; } else { scanf(" %lf", valore2); if (!(*valore2 >= min && *valore2 <= max)) sentinella = -1; } if (sentinella != 0) printf("Error: input out of range (%d ~ %d). Insert value again:\n", min, max); } while (sentinella != 0); } void wanna_change(char *change) { printf("Do you want to change any (other) conversion parameters? (y/n) "); yes_or_no(change); } void band_check(int lpf_on, int hpf_on, double *lpf_f, double *hpf_f) { /* dichiarazione variabili locali */ double diff = 0, scarto = 0, temp; /* messages */ char *msg[7] = {"Error: all signal spectrum will be lost with current cut off frequencies.\n", "Low Pass Cut Off Frequency set to", "hz", "Error: banda minima non garantita.\n", "High Pass Cut Off Frequency set to", "Low Pass Filter Cut Off Frequency is OK", "High Pass Filter Cut Off Frequency is OK"}; if (lpf_on && hpf_on) { if (*hpf_f > *lpf_f) { temp = *lpf_f; *lpf_f = *hpf_f; *hpf_f = temp; printf("High and Low Pass Filter Frequencies have been inverted\n"); } if ((diff = *lpf_f - *hpf_f) < glob_bsm) { scarto = glob_bsm - diff; if (scarto > 0) { if (scarto > *hpf_f - LIU) { scarto -= *hpf_f - LIU; *hpf_f = LIU; printf("%s %.3f %s\n", msg[4], *hpf_f, msg[2]); *lpf_f += scarto; printf("%s %.3f %s\n", msg[1], *lpf_f, msg[2]); } else { *hpf_f -= scarto; printf("%s %.3f %s\n", msg[4], *hpf_f, msg[2]); } } } } else if (lpf_on) { if (*lpf_f < glob_bsm) { /* caso a b */ printf("%s", msg[3]); *lpf_f = glob_bsm; printf("%s %.3f %s\n", msg[1], *lpf_f, msg[2]); } else /* caso c */ printf("%s", msg[5]); } else { /* hpf_on */ if (LSU - *hpf_f < glob_bsm) { /* caso a b */ printf("%s", msg[3]); *hpf_f = LSU - glob_bsm; printf("%s %.3f %s\n", msg[1], *hpf_f, msg[2]); } else /* caso c */ printf("%s", msg[6]); } printf("%s (%.3f %s)\n%s (%.3f %s)\n", msg[5], *lpf_f, msg[2], msg[6], *hpf_f, msg[2]); }