Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
РПЗ.docx
Скачиваний:
22
Добавлен:
09.02.2015
Размер:
518.47 Кб
Скачать

3.2 Реализация звукового потока и привязка к интерфейсу

Сразу приступим к обсуждению файла gsprog.c, в котором реализована программа для звука.

#include <stdio.h> //Подключаем стандартные функции i/o

#include <gtk/gtk.h> //библиотеки интерфейса

#include <gdk/gdk.h> //----||----

#include <gdk/gdkx.h> //----||----

#include <gst/gst.h> //библиотеки gstreamer

#define DEFAULT_FILE "/home/" //путь к нашему файлу

//глобальные переменные для перестраховки

extern GtkAdjustment *adj_progress; //значение ползунка поиска

extern GtkWidget *time_display, *window; //основное окно

GstElement *pipeline; //конвейер

GstElement *filesrc; //чтение файла

GstElement *decoder; //преобразование звука в отсчеты

GstElement *dec1;

GstElement *queueaudio;

GstElement *sink; //воспроизведение звука звуковым драйвером

GstElement *volume; //управление громкостью

GstElement *echo; //звуковой эффект эхо

GstElement *equalizer;//эквалайзер

GstElement *vsink;

GstElement *audioconvert1;

GstElement *audioconvert2;

GstElement *audioconvert3;

gboolean playing = FALSE;

gboolean connected = TRUE;

static gboolean gstreamer_print_position();

int gstreamer() {

GMainLoop *loop; //основной цикл

/*--------------------------------------------

СОЗДАЕМ ЗВУКОВОЙ КОНВЕЙЕР

----------------------------------------------*/

//инициализируем объявленные элементы

//этот кусок практически полностью соответствует методическим //указаниям

pipeline = gst_pipeline_new("my_pipe");

filesrc = gst_element_factory_make("filesrc", "mysrc");

decoder = gst_element_factory_make("mad", "mydec");

sink = gst_element_factory_make("autoaudiosink", "sink");

equalizer = gst_element_factory_make("equalizer-10bands", "my_equal");

decoder = gst_element_factory_make("mad", "mydec4");

echo = gst_element_factory_make("audioecho", "echo");

volume = gst_element_factory_make("volume", NULL);

audioconvert1 = gst_element_factory_make("audioconvert", "conv1");

audioconvert2 = gst_element_factory_make("audioconvert", "conv2");

audioconvert3 = gst_element_factory_make("audioconvert", "conv3");

queueaudio = gst_element_factory_make("queue2", "aqueue");

//установка эффекта эхо

g_object_set(G_OBJECT(echo), "max-delay", 1000000000, NULL);

//передаём элементу filesrc параметр location

g_object_set(G_OBJECT(filesrc), "location", DEFAULT_FILE, NULL);

//запускаем конвейер

gst_bin_add_many(GST_BIN(pipeline), filesrc, decoder, audioconvert3,

queueaudio, audioconvert2, equalizer, audioconvert1, echo, volume, sink, NULL);

//соединяем элементы последовательно

gst_element_link_many(filesrc, decoder, audioconvert3, NULL);

gst_element_link(audioconvert3, queueaudio);

gst_element_link_many(queueaudio, audioconvert2, equalizer, audioconvert1, echo, volume, sink, NULL);

//запускаем основной цикл

loop = g_main_loop_new(NULL, FALSE);

g_print("ok\n");

g_main_loop_run(loop);

gst_element_set_state(pipeline, GST_STATE_NULL);

gst_element_set_state(pipeline, GST_STATE_PLAYING);

return 0;

}

/*--------------------------------------------

ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ

----------------------------------------------*/

//функция реализует изменение громкости

void gstreamer_volume(GtkWidget *vol, gpointer data) {

//значение с кнопки громкости

gdouble v = gtk_scale_button_get_value(GTK_SCALE_BUTTON(vol));

//установка громкости

g_object_set(G_OBJECT(volume), "volume", v, NULL);

//вывод громкости в процентах

g_print("vol: %.0lf%\n", v * 100);

}

//функция реализует эффект phaser через echo

void gstreamer_echo() {

guint64 delay = 100000; //задержка в нс

guint64 max_delay = 1; //максимальная задержка

gfloat feedback = 0.0; //обратная связь

gfloat inten = 0.1; //интенсивность

g_print("phaser on\n");

g_object_set(G_OBJECT(echo), "delay", delay, "feedback", feedback, "intensity", inten, "max-delay" , max_delay, NULL );

}

//эта функция работает, когда эффект выключен

void gstreamer_echo_stop() {

//параметры аналогичные предыдущей функции

guint64 delay = 1;

guint64 max_delay = 1;

gfloat feedback = 0.0000;

gfloat inten = 0.0001;

g_print("phaser off\n");

g_object_set(G_OBJECT(echo),"delay", delay, "feedback", feedback, "intensity", inten, "max-delay" , max_delay, NULL );

}

//функция обрабатываетвключение и выключение phaser

void gstreamer_toggle(GtkWidget *check, gpointer data) {

if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {

//gstreamer_echo_stop();

gstreamer_echo();

}

else

gstreamer_echo_stop();

}

//функция реализует 7 полосный эквалайзер

void gstreamer_equalizer(GtkAdjustment *adj, gpointer num) {

GstObject *band;

int numBand = GPOINTER_TO_INT(num); //номер полосы

gdouble cs = gtk_adjustment_get_value(adj);

//значения с ползунков

//конструкция с параментрами полос

typedef struct {

gfloat freq; //средняя частота

gfloat width; //ширина полосы

gfloat gain; //усиление в dB

} GstEqualizerBandState;

//инициализируем конструкцию, объявляем значения всех 7 полос

GstEqualizerBandState state[] = {

//графу усиления пока оставляем нулевой

{90.0, 70.0, 0.0},

{400.0, 240.0, 0.0},

{970.0, 330.0, 0.0},

{1900.0, 600.0, 0.0},

{3750.0, 1250.0, 0.0},

{7500.0, 2500.0, 0.0},

{15000.0, 5000.0, 0.0}

};

//теперь заполняем графу усиление, передавая параметры с ползунков

state[numBand].gain = cs;

//изменяем звук в соответствии с полученными данными

band = gst_child_proxy_get_child_by_index (GST_CHILD_PROXY (equalizer), numBand);

g_object_set(G_OBJECT(band), "freq", state[numBand].freq, "bandwidth", state [numBand].width, "gain", state[numBand].gain);

g_object_unref (G_OBJECT (band));

}

//функция обрабатывает воспроизведение

int gstreamer_play() {

playing = TRUE;

g_timeout_add(500, (GSourceFunc)gstreamer_print_position, NULL);

gst_element_set_state(pipeline, GST_STATE_PLAYING);

g_print("action: playing\n");

return 0;

}

//функция обрабатывает паузу

int gstreamer_pause() {

playing = FALSE;

gst_element_set_state(pipeline, GST_STATE_PAUSED);

g_print("action: paused\n");

return 0;

}

//функция обрабатывает остановку

int gstreamer_stop() {

playing = FALSE;

g_timeout_add(500, (GSourceFunc)gstreamer_print_position, NULL);

gst_element_set_state(pipeline, GST_STATE_NULL);

g_print("action: stopped\n");

return 0;

}

//функция обрабатывает поиск по треку

static void gstreamer_seek_to_time(GtkAdjustment *ad) {

if(connected) {

gdouble val = gtk_adjustment_get_value(ad);

gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,

GST_SEEK_TYPE_SET, val,

GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);

}

}

//функция выводит позицию в песне

static gboolean gstreamer_print_position() {

gint64 pos, dur;

GstFormat time = GST_FORMAT_TIME;

gchar progress_text[100];

gst_element_query_position(pipeline, &time, &pos);

gst_element_query_duration(pipeline, &time, &dur);

gint seconds = pos / GST_SECOND;

gint minutes = seconds / 60;

gint seconds_dur = dur / GST_SECOND;

gint minutes_dur = seconds_dur / 60;

sprintf (progress_text, " %d:%02d / %d:%02d ", minutes,

seconds - minutes * 60, minutes_dur, seconds_dur - minutes_dur * 60);

connected = FALSE;

gtk_adjustment_set_upper(adj_progress, dur);

gtk_adjustment_set_value(adj_progress, pos);

connected = TRUE;

gtk_label_set_label(GTK_LABEL(time_display),progress_text);

return playing;

}

Теперь у нас есть все для работающей программы, можно все это собирать вместе и смотреть на работу плеера.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]