spek

Acoustic spectrum analyser
git clone http://git.hanabi.in/repos/spek.git
Log | Files | Refs | README

commit f46f1fc9ae310294c48614390a2b59e7966e70e0
parent 9db2524bdf1e57b2bbac64c002064b86a66523cc
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date:   Thu, 20 May 2010 21:32:06 +1000

Show stream info in the window (issue 7)

Diffstat:
Msrc/spek-source.vala | 69++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/spek-spectrogram.vala | 33++++++++++++++++++++++++++++++---
2 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/src/spek-source.vala b/src/spek-source.vala @@ -26,11 +26,18 @@ namespace Spek { public int samples { get; construct; } public int threshold { get; construct; } // TODO: file a bug, cannot s/set/construct/ - public Callback callback {get; set; } + public DataCallback data_cb { get; set; } + public InfoCallback info_cb { get; set; } + public int64 duration { get; private set; default = 0; } public int rate { get; private set; default = 0; } + public string audio_codec { get; private set; default = null; } + public uint bitrate { get; private set; default = 0; } + public int channels { get; private set; default = 0; } + public int depth { get; private set; default = 0; } - public delegate void Callback (int sample, float[] values); + public delegate void DataCallback (int sample, float[] values); + public delegate void InfoCallback (); private Pipeline pipeline = null; private Element spectrum = null; @@ -39,9 +46,12 @@ namespace Spek { private float[] values; private uint watch_id; - public Source (string file_name, int bands, int samples, int threshold, Callback callback) { + public Source ( + string file_name, int bands, int samples, int threshold, + DataCallback data_cb, InfoCallback info_cb) { GLib.Object (file_name: file_name, bands: bands, samples: samples, threshold: threshold); - this.callback = callback; + this.data_cb = data_cb; + this.info_cb = info_cb; } public void stop () { @@ -84,10 +94,15 @@ namespace Spek { var caps = pad.get_caps (); for (int i = 0; i < caps.get_size (); i++) { var structure = caps.get_structure (i); - int rate; - if (structure.get_int ("rate", out rate) && rate > 0) { - this.rate = rate; - break; + int n = 0; + if (rate == 0 && structure.get_int ("rate", out n)) { + rate = n; + } + if (channels == 0 && structure.get_int ("channels", out n)) { + channels = n; + } + if (depth == 0 && structure.get_int ("depth", out n)) { + depth = n; } } @@ -138,14 +153,42 @@ namespace Spek { private bool on_bus_watch (Bus bus, Message message) { var structure = message.get_structure (); - if (message.type == MessageType.ELEMENT && structure.get_name () == "spectrum") { - var magnitudes = structure.get_value ("magnitude"); - for (int i = 0; i < bands; i++) { - values[i] = magnitudes.list_get_value (i).get_float (); + switch (message.type ) { + case MessageType.ELEMENT: + if (structure.get_name () == "spectrum") { + var magnitudes = structure.get_value ("magnitude"); + for (int i = 0; i < bands; i++) { + values[i] = magnitudes.list_get_value (i).get_float (); + } + data_cb (sample++, values); } - callback (sample++, values); + break; + case MessageType.TAG: + TagList tag_list; + message.parse_tag (out tag_list); + tag_list.foreach (on_tag); + break; } return true; } + + private void on_tag (TagList tag_list, string tag) { + switch (tag) { + case TAG_AUDIO_CODEC: + string s = null; + if (audio_codec == null && tag_list.get_string (tag, out s)) { + audio_codec = s; + info_cb (); + } + break; + case TAG_BITRATE: + uint u = 0; + if (bitrate == 0 && tag_list.get_uint (tag, out u)) { + bitrate = u; + info_cb (); + } + break; + } + } } } \ No newline at end of file diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala @@ -25,6 +25,7 @@ namespace Spek { public string file_name { get; private set; } private Source source; + private string info; private const int THRESHOLD = -92; private const int BANDS = 1024; @@ -52,6 +53,7 @@ namespace Spek { public void open (string file_name) { this.file_name = file_name; + this.info = ""; start (); } @@ -72,7 +74,7 @@ namespace Spek { int samples = allocation.width - LPAD - RPAD; if (samples > 0) { image = new ImageSurface (Format.RGB24, samples, BANDS); - source = new Source (file_name, BANDS, samples, THRESHOLD, source_callback); + source = new Source (file_name, BANDS, samples, THRESHOLD, data_cb, info_cb); } else { image = null; source = null; @@ -88,7 +90,7 @@ namespace Spek { } } - private void source_callback (int sample, float[] values) { + private void data_cb (int sample, float[] values) { for (int y = 0; y < values.length; y++) { var level = double.min ( 1.0, Math.log10 (1.0 - THRESHOLD + values[y]) / Math.log10 (-THRESHOLD)); @@ -97,6 +99,31 @@ namespace Spek { queue_draw_area (LPAD + sample, TPAD, 1, allocation.height - TPAD - BPAD); } + private void info_cb () { + string[] items = {}; + if (source.audio_codec != null) { + items += source.audio_codec; + } + if (source.bitrate != 0) { + items += _("%d kbps").printf (source.bitrate / 1000); + } + if (source.rate != 0) { + items += _("%d Hz").printf (source.rate); + } + // Show sample rate only if there is no bitrate. + if (source.depth != 0 && source.bitrate == 0) { + items += _("%d bits").printf (source.depth); + } + if (source.channels != 0) { + items += ngettext ("%d channel", "%d channels", source.channels). + printf (source.channels); + } + if (items.length > 0) { + info = string.joinv (", ", items); + queue_draw_area (LPAD, 0, allocation.width - LPAD - RPAD, TPAD); + } + } + private override bool expose_event (EventExpose event) { var cr = cairo_create (this.window); @@ -160,7 +187,7 @@ namespace Spek { // File properties. cr.set_font_size (11.0); cr.move_to (LPAD, TPAD - GAP); - //cr.show_text (trim (cr, "MPEG 1 Audio, Layer 3 (MP3), 320 kbps, 44100 Hz, 2 channels", w - LPAD - RPAD, true)); + cr.show_text (trim (cr, info, w - LPAD - RPAD, true)); FontExtents ext; cr.font_extents (out ext);