Skip to content

Instantly share code, notes, and snippets.

@MayamaTakeshi
Created December 25, 2022 02:19
Show Gist options
  • Save MayamaTakeshi/282d7fefed0dcab5b3938bf0f3f3b079 to your computer and use it in GitHub Desktop.
Save MayamaTakeshi/282d7fefed0dcab5b3938bf0f3f3b079 to your computer and use it in GitHub Desktop.
Gstreamer DTMF detection plugin in vala written by ChatGPT
using Gst;
using GLib;
public class DtmfDetector : Element {
private static const int SAMPLE_RATE = 8000;
private static const int CHUNK_SIZE = 256;
private static const int LOW_FREQUENCIES = [697, 770, 852, 941];
private static const int HIGH_FREQUENCIES = [1209, 1336, 1477, 1633];
private Gst.Pad sinkpad;
private Gst.Pad srcpad;
private GLib.Queue<char> tones;
private GLib.Mutex mutex;
public DtmfDetector(Gst.ElementFactory factory, string name) {
this.tones = new GLib.Queue<char>();
this.mutex = new GLib.Mutex();
this.sinkpad = this.get_static_pad("sink");
this.srcpad = this.get_static_pad("src");
this.sinkpad.add_probe(PadProbeType.BUFFER, sink_probe);
}
private PadProbeReturn sink_probe(Pad pad, PadProbeInfo info) {
var buffer = info.get_buffer();
var data = buffer.extract_dup(0, buffer.get_size());
var samples = data.get_int16_array();
var magnitudes = new double[CHUNK_SIZE];
for (int i = 0; i < CHUNK_SIZE; i++) {
var sample = samples[i];
var magnitude = 0.0;
for (int j = 0; j < LOW_FREQUENCIES.length; j++) {
var lowFrequency = LOW_FREQUENCIES[j];
var highFrequency = HIGH_FREQUENCIES[j];
var lowReal = Math.cos(2 * Math.PI * lowFrequency * i / SAMPLE_RATE);
var lowImag = Math.sin(2 * Math.PI * lowFrequency * i / SAMPLE_RATE);
var highReal = Math.cos(2 * Math.PI * highFrequency * i / SAMPLE_RATE);
var highImag = Math.sin(2 * Math.PI * highFrequency * i / SAMPLE_RATE);
magnitude += lowReal * sample + highReal * sample;
}
magnitudes[i] = magnitude;
}
var maxMagnitude = -1.0;
var maxFrequency = -1;
for (int i = 0; i < CHUNK_SIZE; i++) {
var magnitude = magnitudes[i];
if (magnitude > maxMagnitude) {
maxMagnitude = magnitude;
maxFrequency = i;
}
}
var frequency = (maxFrequency / CHUNK_SIZE) * SAMPLE_RATE;
var tone = '?';
if (697 <= frequency && frequency <= 1209) {
var row =
if (697 <= frequency && frequency <= 770) {
"1"
} else if (770 <= frequency && frequency <= 852) {
"2"
} else if (852 <= frequency && frequency <= 941) {
"3"
} else {
"A"
};
tone = row[0];
} else if (1336 <= frequency && frequency <= 1477) {
var column =
if (1336 <= frequency && frequency <= 1477) {
"4"
} else if (1477 <= frequency && frequency <= 1633) {
"5"
} else {
"6"
};
tone = column[0];
} else if (1633 <= frequency && frequency <= 1209) {
var row =
if (1633 <= frequency && frequency <= 1750) {
"7"
} else if (1750 <= frequency && frequency <= 1865) {
"8"
} else if (1865 <= frequency && frequency <= 1976) {
"9"
} else {
"*"
};
tone = row[0];
} else if (2277 <= frequency && frequency <= 1633) {
var column =
if (2277 <= frequency && frequency <= 2024) {
"0"
} else {
"#"
};
tone = column[0];
}
mutex.lock();
tones.push_tail(tone);
mutex.unlock();
return PadProbeReturn.OK;
}
public char get_tone() {
mutex.lock();
var tone = tones.pop_head();
mutex.unlock();
return tone;
}
}
public static int plugin_init(Plugin plugin) {
return Element.register(plugin, "dtmfdetector", 0, DtmfDetector.GTYPE);
}
// Sample usage
Gst.init(ref args);
var pipeline = new Pipeline("pipeline");
var source = ElementFactory.make("autoaudiosrc", "source");
var dtmfdetector = ElementFactory.make("dtmfdetector", "dtmfdetector");
var sink = ElementFactory.make("autoaudiosink", "sink");
pipeline.add(source).add(dtmfdetector).add(sink);
source.link(dtmfdetector).link(sink);
pipeline.set_state(State.PLAYING);
while (true) {
var tone = dtmfdetector.get_tone();
stdout.printf("Detected tone: %c\n", tone);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment