Created
December 25, 2022 02:19
-
-
Save MayamaTakeshi/282d7fefed0dcab5b3938bf0f3f3b079 to your computer and use it in GitHub Desktop.
Gstreamer DTMF detection plugin in vala written by ChatGPT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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