FD Tone Notify - New Tone Detection Software Released

DC31

Member
Feed Provider
Joined
Feb 19, 2011
Messages
1,545
Location
Massachusetts
Have you installed pavucontrol? With that, when you start up the Tone Notify program it will appear in the Recording tab. From there you can click on the input device and choose from the list.
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
I do have pavucontrol. Nothing appears in the recording tab when I run FD Tone Notify. I’ve tried asound.conf with hw:1,0 hw:0,0 and using dsnoop in JSON.. can’t get it to show up as a recording device..
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
I do have pavucontrol. Nothing appears in the recording tab when I run FD Tone Notify. I’ve tried asound.conf with hw:1,0 hw:0,0 and using dsnoop in JSON.. can’t get it to show up as a recording device..

I’ve gotten the recording device to show up in the recordings tab by simply using “pulse” for inputDevice in the json config file. I’ll continue testing and report back.
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
Ok, FD seems to be working as expected using “pulse” for the inputDevice and each instance shows up in pavucontrol.

I can not seem to get each instance to use its own json config though. It is my understanding from the documentation that; —instance-name my-fd should load a config file named default-my-fd.json “AND” local-my-fd.json… However, there is no mention of local-my-fd.json anywhere else in the documentation amd I’m not sure what should be in there.

Additionally, the only thing I need FD Tone Notify to do is to run an external command. I don’t need it to record or send emails or anything else but run a local command. Would I configure it to do this by simply removing all of the rest of the parameters except externalCommand from the json file? As for inhibiting recording, will setting minRecordingLengthSec to “0” stop the recording function altogether or does that only establish a minimum recording time should silence be detected the input?
 

Reconrider

Active Member
Joined
Sep 26, 2017
Messages
1,756
Location
EST
Wow I some how missed this being posted back in march.

I don't use a current fire tone out, but I might start using it to find some missing fire tones, or even use it to figure out who is who when hunting
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
Wow I some how missed this being posted back in march.

I don't use a current fire tone out, but I might start using it to find some missing fire tones, or even use it to figure out who is who when hunting
It took me a week of looking and a good 5 hours of some serious scouring to find it... It's wonderful by the way.. Works like a charm.

I still haven't been able to get the multi instance to work as intended in the documentation but I worked around it by simply making 4 copies of the folder and then changing the setting for each one.. If you're using pulseaudio, it works great! I'm not sure about ALSA but simply using "pulse" in the inputDevice gave me everything I needed! It's really great!
 

Reconrider

Active Member
Joined
Sep 26, 2017
Messages
1,756
Location
EST
It took me a week of looking and a good 5 hours of some serious scouring to find it... It's wonderful by the way.. Works like a charm.

I still haven't been able to get the multi instance to work as intended in the documentation but I worked around it by simply making 4 copies of the folder and then changing the setting for each one.. If you're using pulseaudio, it works great! I'm not sure about ALSA but simply using "pulse" in the inputDevice gave me everything I needed! It's really great!
I would be using this on my winfroze computer just for ease of attachment to my dsdplus. But either way, I'm happy I found this. I won't need the email feature as i only want to see who has what tone outs
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
I would be using this on my winfroze computer just for ease of attachment to my dsdplus. But either way, I'm happy I found this. I won't need the email feature as i only want to see who has what tone outs
You probably need to use VB-Cable (if you don't already) but, I suspect it'll be just as easy to get setup on Windows.
 

kevind963

Member
Feed Provider
Joined
Jun 22, 2012
Messages
46
@KN4GRO
Sorry for not getting back on here sooner. Its been a busy couple days for me.

Glad that you have everything working for the most part. I've never used pavucontrol before but it sounds like it is a useful tool and it may be worth adding what you had to do to the documentation to help future users.

As far as the issue with instances. FD Tone Notify uses a package config for "picking" the config file. Its a fairly big package with lots going on but is very flexible. FD Tone Notify allows the --instance-name option to override the NODE_APP_INSTANCE environment variable which should allow you to use the same directory without copy pasting it a whole bunch of times. You would need to create a config file 'default-my-fd.json' and that should work. Note that if you have a 'default.json' that it loads that first and then overrides it with the more specific one. That might be causing problems. If it is still giving you problems start it up with --silly, --instance-name and a copy paste/screenshot of the files in your config directory.

I've never tried setting the recording length to zero. Hopefully that works... If not something to fix. Feel free to add a no recording option as a feature request on GitHub. Issues · kjdElectronics/fd-tone-notify
 

iamhere300

Member
Joined
Jun 27, 2004
Messages
1,346
Location
Chappell Hill TX
So....

Has anyone had any luck uploading these automatically to Facebook? Possibly something that can be added without too much trouble? Sort of like "how to post for idiots"?
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
@KN4GRO
Sorry for not getting back on here sooner. Its been a busy couple days for me.

Glad that you have everything working for the most part. I've never used pavucontrol before but it sounds like it is a useful tool and it may be worth adding what you had to do to the documentation to help future users.

As far as the issue with instances. FD Tone Notify uses a package config for "picking" the config file. Its a fairly big package with lots going on but is very flexible. FD Tone Notify allows the --instance-name option to override the NODE_APP_INSTANCE environment variable which should allow you to use the same directory without copy pasting it a whole bunch of times. You would need to create a config file 'default-my-fd.json' and that should work. Note that if you have a 'default.json' that it loads that first and then overrides it with the more specific one. That might be causing problems. If it is still giving you problems start it up with --silly, --instance-name and a copy paste/screenshot of the files in your config directory.

I've never tried setting the recording length to zero. Hopefully that works... If not something to fix. Feel free to add a no recording option as a feature request on GitHub. Issues · kjdElectronics/fd-tone-notify
Kevin, you're the best!!

I do have a question for you that maybe you can help with..

After testing for about 20 hours or so, I have noticed that at some random interval (hours), I get this: Alert: No mic data for 30 Sec, followed by a Warning: Restarting mic instance...

I looked at AudioService.js to try and understand why this is happening and for what reason.. I notice that you have an interval setup which you call NO_DATA_SERVICE_INTERVAL.. with a value of 30 SEC

I'm not 100% certain but I'm assuming that this interval is somehow used in conjunction with the silence threshold. (Maybe to detect an unplugged analog input?)

Anyhow, the following ends up happening when the mic is "restarted."

When using pulseaudio and further in particular, using multiple instances, the mic (recording device) gets set back to default (input device), or, in most cases, the "last used" input device...

I am running 4 SDRs using pulsaudio sinks to map these SDRs from a playback to an input device with a corresponding name, (for example; north, central, west, south) I can then choose to map a "recording instance" from FD to its corresponding input.

The mapping looks something like this, in this order:

OP25playback: ALSA Playback -----> Output: north ------> InputMonitor: north ------>FD Tone Notify Mic (recordInstance): north
OP25playback: ALSA Playback -----> Output: central ------> InputMonitor: central ------>FD Tone Notify Mic (recordInstance): central
OP25playback: ALSA Playback -----> Output: west ------> InputMonitor: west ------>FD Tone Notify Mic (recordInstance): west
OP25playback: ALSA Playback -----> Output: south ------> InputMonitor: south ------>FD Tone Notify Mic (recordInstance):south

When FD Tone Notify reaches its interval, which seems to happen at exactly the same time on all four instances (not always all four though) and not in 30 seconds but in HOURS, all four mics are reset and the resulting mapping ends up looking like some variation of this:

OP25playback: ALSA Playback -----> Output: north ------> InputMonitor: north ------>FD Tone Notify Mic (recordInstance): south
OP25playback: ALSA Playback -----> Output: central ------> InputMonitor: central ------>FD Tone Notify Mic (recordInstance): south
OP25playback: ALSA Playback -----> Output: west ------> InputMonitor: west ------>FD Tone Notify Mic (recordInstance): south
OP25playback: ALSA Playback -----> Output: south ------> InputMonitor: south ------>FD Tone Notify Mic (recordInstance): south

You can imagine my surprise when I was notified of tone on ALL FOUR CHANNELS at 4am!! HAHAHAHAHA!!! Thought the aliens had finally landed!!

Now I suppose I could solve this one of several ways...

1. Figure out the configuration parameters I need to make sure that the above map is always respected by predefining or forcing a particular instance of FD Tone Notify to connect a mic to a specific predefined input. i.e. FDToneNotify --instance a (config file option for input name) or, --input-name "north" or something like that.

2. Write out some script that will remap everything back in to place at particular intervals (seems less efficient but probably doable)

I went with option 3. Change the NO_DATA_SERVICE_INTERVAL from 30 SEC to 86400 SEC :cool: (don't judge me, its Sunday)

Anyhow, all jokes aside, I'd really like to understand what this NO_DATA_SERVICE_INTERVAL is intended to do. Any insight you can help with would be much appreciated!

Thanks again!!
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
So....

Has anyone had any luck uploading these automatically to Facebook? Possibly something that can be added without too much trouble? Sort of like "how to post for idiots"?

I mean, you could probably find some python script or something that posts to facebook and then just add that script to the "externalCommand" --Just a thought...
 

johnmac

Member
Feed Provider
Joined
Oct 6, 2003
Messages
159
Location
Westminster, Ma
I have windows 10 x64. Downloaded both FD Notify and sox. Created the path for sox. Ran FD notify, it created the config files, but nothing else. Is there something I am missing? I see no user interface or any indication that the program is running.
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
I have windows 10 x64. Downloaded both FD Notify and sox. Created the path for sox. Ran FD notify, it created the config files, but nothing else. Is there something I am missing? I see no user interface or any indication that the program is running.
I'm no expert but, I believe that FD Tone Notify is a command line only program. Check the documentation for how to run it, where to change the config files and what arguments to use for example:

Code:
fd-tone-notify.exe --web-server --port 3000

or

Code:
 fd-tone-notify.exe --tone-detector --web-server

You should probably also use an elevated command prompt or powershell
 

kevind963

Member
Feed Provider
Joined
Jun 22, 2012
Messages
46
@KN4GRO
So the NO_DATA_INTERVAL_SEC was my hacky solution to a problem a did not want to actually find the source of. After some variable amount of time audio input would stop being processed for an unknown reason. The mic instance simply would stop recording data. My solution was simply restart the mic instance. This is triggered after not receiving ANY data after the NO_DATA_INTERVAL_SEC interval because under normal conditions it is always getting data even if the data is "nothing/silence".

So with your fix it will just stop logging and alerting at a certain point because there will be no data to process.

When it restarts it runs the same code as when it starts. Add this line after line 37:
JavaScript:
log.silly(`Setting up mic instnace with device ${config.audio.inputDevice}`);

Perhaps the config is getting override somewhere and it is getting defaulted. This will tell us for sure.
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
@KN4GRO
So the NO_DATA_INTERVAL_SEC was my hacky solution to a problem a did not want to actually find the source of. After some variable amount of time audio input would stop being processed for an unknown reason. The mic instance simply would stop recording data. My solution was simply restart the mic instance. This is triggered after not receiving ANY data after the NO_DATA_INTERVAL_SEC interval because under normal conditions it is always getting data even if the data is "nothing/silence".

So with your fix it will just stop logging and alerting at a certain point because there will be no data to process.

When it restarts it runs the same code as when it starts. Add this line after line 37:
JavaScript:
log.silly(`Setting up mic instnace with device ${config.audio.inputDevice}`);

Perhaps the config is getting override somewhere and it is getting defaulted. This will tell us for sure.

I'll give that a try but I don't think the config is being overwritten. I think pulseaudio is simply doing what pulsaudio does.

In order to "send" the audio from an input to a newly created recording device, a specific loopback has to be established, otherwise, pulse just grabs either the "default" input, or whatever the last input was, whichever takes precedence. (not sure how pulse decides which to use)...

Ideally, to solve this issue, we should be able to specify (within the json config) that this.instance should create a recording device using pulse and that this.recordingDevice should listen to a specifically named input device....

I have no idea how to write this to be honest...

Specifying "pulse" as the inputDevice gets us half way there...

Specifying "pulse [with a specific input name]" would get us all the way there... <---- I have no idea how to do this....
 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
I'll give that a try but I don't think the config is being overwritten. I think pulseaudio is simply doing what pulsaudio does.

In order to "send" the audio from an input to a newly created recording device, a specific loopback has to be established, otherwise, pulse just grabs either the "default" input, or whatever the last input was, whichever takes precedence. (not sure how pulse decides which to use)...

Ideally, to solve this issue, we should be able to specify (within the json config) that this.instance should create a recording device using pulse and that this.recordingDevice should listen to a specifically named input device....

I have no idea how to write this to be honest...

Specifying "pulse" as the inputDevice gets us half way there...

Specifying "pulse [with a specific input name]" would get us all the way there... <---- I have no idea how to do this....

This may give us some clues…

 

KN4GRO

Member
Joined
Sep 15, 2010
Messages
41
I'll give that a try but I don't think the config is being overwritten. I think pulseaudio is simply doing what pulsaudio does.

In order to "send" the audio from an input to a newly created recording device, a specific loopback has to be established, otherwise, pulse just grabs either the "default" input, or whatever the last input was, whichever takes precedence. (not sure how pulse decides which to use)...

Ideally, to solve this issue, we should be able to specify (within the json config) that this.instance should create a recording device using pulse and that this.recordingDevice should listen to a specifically named input device....

I have no idea how to write this to be honest...

Specifying "pulse" as the inputDevice gets us half way there...

Specifying "pulse [with a specific input name]" would get us all the way there... <---- I have no idea how to do this....


Hello all, just for reference, when wanting to point to a specific sink within the pulse server, it is a matter of simply using:

Code:
pulse:sinkname
Thanks for the hint kevind963!

I have put together a system that has 4 SDR's controlled by OP25. Each SDR is tuned to a specific talk group on a trunked system in my area (we'll call these north, central, west and south.) and FD Tone Notify is "listening" for tones in each area independently. More on this later...


Allow me to provide an example as it pertains to FD Tone Notify and Linux... Maybe this will help some other noob, just like me, in the future...

When you run OP25, if you choose to output the audio to the sound card, it creates a "playback" named: 'ALSA plug-in [python3.8]' (sometimes also called OP25: ALSA Playback depending on how you run OP25)

When you run an instance of FD Tone Notify, it does something similar but instead it creates a "record" (think "virtual" microphone) named: 'ALSA plug-in [aplay]'

So how do you make a "record" listen to the audio coming from a "playback?"

The simple answer is: If you're using pulseaudio, you first need to create a "null-sink" (think "virtual" cable that isn't plugged in anywhere...yet)

To create a null sink AND give it a name (name is important) you head out to a terminal window and type the following:

Code:
pactl load-module module-null-sink sink_name=north sink_properties=device.description="north"

Why north? Well, you can make it whatever you want... I chose north because in my area, the four channels I'm monitoring are referred to as North District, Central District, and so on...

Now that you have a null sink (virtual cable that isn't plugged into anything) you can head over to pavucontrol and you will see both an output device called "north" and an input device called "Monitor of north" Think of these as two ends of our virtual cable...

<<<north output--------- lonely virtual cable with nothing to do yet (also called a null-sink) ---------input Monitor of north>>>

Since there is nothing being fed through this virtual cable yet, we need to do that next.

In pavucontrol, in the Playback tab, find your OP25 Playback and over on the right hand side you'll see a button that allows you to choose which "output" you want to playback on. Go ahead a choose "north" here.. Now we've plugged in the output side of our virtual cable. The other end, "input," still isn't plugged into anything. So head on over to the "Recording" tab and find your [aplay] plug-in and over on the right hand side you'll see a button that allows you to choose which "input" you want your record device to listen to.. Go ahead and choose "Monitor of north" here. Now that you've virtually plugged in both ends of your cable, you end up with something like this:

OP25: Playback <<<north output--------- happy cable with audio flowing through it ---------input Monitor of north>>> FD Tone Notify Record

So now we've got what we need, everything should be fine, right? Well, not exactly... You see, everything we've done here will not survive a machine reboot or restarting of either FD Tone Notify or OP25.... Further, OP25 and in fact anything that you point at pulseaudio tends to "fallback" on either the last output used by pavucontrol or simply point to the default output as defined system wide or user specific conf files.. Multiply this problem by 4 channels and you can very quickly start to see the problem here... So what's the answer?

Well for starters we have to make our "virtual cables (null-sinks)" permanent, so that they survive a system reboot. To do this, you will need to make a simple change to your /etc/pulse/default.pa

The easiest way to do this is to use the following command from terminal:
Code:
sudo nano /etc/pulse/default.pa

You're going to want create the null sink much like we did above but, drop the pactl from the beginning of the line. Do this for each permanent virtual cable you want to load with your system. in my case I added four lines. Like this:
Code:
load-module module-null-sink sink_name=north sink_properties=device.description="north"
load-module module-null-sink sink_name=central sink_properties=device.description="central"
load-module module-null-sink sink_name=west sink_properties=device.description="west"
load-module module-null-sink sink_name=south sink_properties=device.description="south"

Now, when I boot my system, all four of my virtual cables are just sitting there, ready for me to use

From here on out, everything gets much easier! All you need to remember is the following: the output side of your cable is called "north" and input side of your cable is called "north.monitor" To connect to either side directly, all you have to do is modify the config file for OP25 and FD Tone Detect to force each instance to connect to a specified end of the specific cable every time it starts an instance...

For example, in the configuration JSON file for FD Tone Notify "/config/default.json" You can specify a device an "inputDevice" in the "audio" section...

In our case, this inputDevice would look like this:
Code:
"inputDevice": "pulse:north.monitor"

Do this in the associated config file of each instance you are running, i.e. central, west, south

Doing this will automatically plug the FD Tone Notify [aplay] device into the "Monitor of north" on the right side of your virtual cable!!! No need to point, click and choose anymore! This is very convenient as you can imagine... Every time the instance starts it will automatically plug itself in to the correct monitor! BEAUTIFUL!!

Now, on the left of our virtual cable (sink), your playback/output side, you want to use pulse:north without ".monitor" This allows us to plug OP25 into the correct output automatically, every time it starts!

If you're using multi_rx.py then you would put the "pulse.north" parameter in "device_name" under the "audio" section like this:
JSON:
"audio": {
"module": [
    {
        "instance_name": "audio1",
        "device_name": "pulse.north",
        "udp_port": "23456",
        "audio_gain": 0.5,
        "number_channels": 1   
    }
]
}

or if you are using rx.py then simply use "pulse.north" after the -O argument, like this:
Code:
./rx.py --nocrypt --args "rtl=0" --gains 'lna:36' -X -q -0 -v 1 -2 -V -O pulse.north -U -w -W 127.0.0.1 -u 23456 -T trunk.tsv -l http://0.0.0.0:8080 2> stderr.2

That's all folks! Do this for every instance and you'll be good to go.. Now, no matter what happens; a system reboot for whatever reason, a need to restart an instance, FD Tone Notify restarting a mic instance because it detected no data after 30 seconds, it should all reconnect itself to your proper audio structure without any interaction at all from you!

It took me quite a bit of digging and reading and sheer frustration to figure this out.. I want to thank everyone on RadioReference who helped me along the way! My only hope is that my writeup here is clear enough to help someone in the future!

If you all want to hear and see the live results of what I, with the help of the wonderful people at RadioReference Forums have accomplished, PM me and I will give you a link to the YouTube channel where all four streams are live. (I'm not sure what the rules are regarding self promotion on RadioReference but I'm pretty sure it's frowned upon so I won't post the link here unless someone says it's ok..)

In addition to four live streams on YouTube, I am using FD Tone Notify to listen for tones and then run an external command. That command is written in python and reaches out to the YouTube API, grabs the appropriate stream, calculates a time stamp, parses together a link and then compiles an alert that gets sent out to both Twitter and a Telegram Channel. When the alert link is clicked, it takes you right to the point in the stream where the alert happened and since the YouTube stream is preserved in perpetuity after a stream ends, the link is clickable whenever you want it!

Thank you again to everyone who helped in any way!
 
Last edited:

johnmac

Member
Feed Provider
Joined
Oct 6, 2003
Messages
159
Location
Westminster, Ma
I have windows 10 x64. Downloaded both FD Notify and sox. Created the path for sox. Ran FD notify, it created the config files, but nothing else. Is there something I am missing? I see no user interface or any indication that the program is running.

Still no luck getting the program to run. This is what I get starting the program with no parameters -

:\WINDOWS\system32>c:\Tone\fd-tone-notify.exe
WARNING: No configurations found in configuration directory:C:\WINDOWS\system32\config
WARNING: To disable this warning set SUPPRESS_NO_CONFIG_WARNING in the environment.
Oct-15-2021 08:40:01 crit : Push Bullet does not have an API Key. Notifications will not be sent
Oct-15-2021 08:40:01 warning : Cannot access secrets file at config/secrets.json. Only using secrets from env Vars
Oct-15-2021 08:40:01 warning : Secret FD_PUSHBULLET_API_KEY has not been set or has an empty value
Oct-15-2021 08:40:01 warning : Secret FD_CORALOGIX_PRIVATE_KEY has not been set or has an empty value
Oct-15-2021 08:40:01 warning : Secret FD_SMTP_USERNAME has not been set or has an empty value
Oct-15-2021 08:40:01 warning : Secret FD_SMTP_PASSWORD has not been set or has an empty value
(node:21384) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'sampleRate' of undefined
at AudioService._setupMic (C:\snapshot\code\service\AudioService.js)
at new AudioService (C:\snapshot\code\service\AudioService.js)
at fdToneNotify (C:\snapshot\code\bin\fdToneNotify.js)
at main (C:\snapshot\code\index.js)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at process.runNextTicks [as _tickCallback] (internal/process/task_queues.js:66:3)
at Function.Module.runMain (pkg/prelude/bootstrap.js:1376:13)
at internal/main/run_main_module.js:17:47
(node:21384) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see Command-line options | Node.js v16.11.1 Documentation). (rejection id: 1)
(node:21384) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

And this is what I get starting the program with the "tone-detector" parameter.

C:\WINDOWS\system32>c:\Tone\fd-tone-notify.exe --tone-detector
error: unknown option '--tone-detector'

Has anyone got this to work on Windows 10?

Thanks, John
 
Top