!7 module ListenOnNoise > DynPrintLogAndEnabled { double minLevel = 20; // percent double maxPause = 1; // pause allowed while we keep recording, seconds double minDuration = 0.5; // min seconds of complete recording to submit double maxDuration = 10; // always stop after this many seconds double extendAfter = 0.5; // seconds to add at the end transient int interval = 100; transient long noiseSince, lastNoise; transient L buffer = synchroList(); transient bool talking; transient TrayIcon externalTrayIcon; start { onChangeAndNow(r { if (enabled && externalTrayIcon == null) externalTrayIcon = installTrayIcon(#1101460, "Alexa Mode (continously listening)", r { dm_activateOSAndModule(module()) }, "Stop Listening", r stopListening); else if (!enabled && externalTrayIcon != null) { removeTrayIcon(externalTrayIcon); externalTrayIcon = null; } }); dm_vmBus_onMessage('talking, r { talking = true }); dm_vmBus_onMessage('doneTalking, r { talking = false }); dm_addAudioListener(voidfunc(short[] data) { if (noiseSince == 0) clear(buffer); buffer.add(cloneShortArray(data)); }); dm_onTopInput(voidfunc(S s) { if "stop listening|voice of" stopListening() }); doEvery(interval, r { if (noiseSince != 0 && elapsedSeconds(noiseSince) >= maxDuration-0.05) { // too long, discard, maybe it's constant noise printWithSeconds("Recording too long (" + maxDuration + " s), discarding"); noiseSince = 0; clear(buffer); } float volume = dm_inputVolumeLevel(); //print("Volume: " + volume); if (volume >= minLevel && !talking) { // got noise lastNoise = sysNow(); if (noiseSince == 0) noiseSince = lastNoise; } else if (noiseSince != 0) { // got no noise, but am recording if (elapsedSeconds(lastNoise) > maxPause-0.05) { double duration = toSeconds(lastNoise-noiseSince+toMS(extendAfter)); if (duration >= minDuration-0.05) { printWithSeconds((enabled ? "Keeping" : "Would keep") + " recording of " + formatDouble(duration, 1) + " seconds"); if (enabled) { L chunks = cloneList(buffer); // drop last silent chunks int len = lengthLevel2_shortArrays(chunks); int wantedLengthInSamples = iround(duration*44100*2); int dropped = 0; while (len-l(last(chunks)) >= wantedLengthInSamples) { len -= l(last(chunks)); popLast(chunks); ++dropped; } //print("Dropped " + n2(dropped, "chunk")); File wavFile = anonymousWAVEFile(); multiShortArraysToWAVE(chunks, wavFile); //printFileInfo(wavFile); vmBus_send('newRecording, wavFile); } } else printWithSeconds("Discarding recording of " + formatDouble(duration, 1) + " seconds"); noiseSince = 0; clear(buffer); } } }); } void cleanMeUp { removeTrayIcon(externalTrayIcon); } void stopListening enter { if (setField(enabled := false)) blipInNewThread(); } }