DiscoverAudio – Gough's Tech ZoneProject: Generate High-Quality Industrial Fire/Alarm Sounder Audio with Python
Project: Generate High-Quality Industrial Fire/Alarm Sounder Audio with Python

Project: Generate High-Quality Industrial Fire/Alarm Sounder Audio with Python

Update: 2024-01-29
Share

Description

I can’t believe how fast 2024 is going by … Australia Day long weekend has already come and gone. Unfortunately for me, I spent it being rather sick with a flu-like illness which I’m still recovering from … but that didn’t stop me from undertaking this rather odd project befitting my rather odd interests.


Motivation


I was browsing through the catalog of element14 on the lookout for specials and things that might be helpful or interesting in my electronics hobby. Often this means browsing through their Connect Magazine, where I have encountered the “Roshni LP Sounder” several times before.



In fact, it’s on some discount right now (note the “01” suffix in the order code), although I will note it was cheaper in the past. This shape is rather recognisable – I’ve seen it in some of my workplace buildings before!


By now you’ve probably realised – that’s a fire sounder and you’d be absolutely correct. This is the thing that makes those noises that warn you to prepare to evacuate and (should all else fail) to actually evacuate the building. In Australia, it’s customary to describe this in WH&S documentation as “beep-beep” and “slow-whoop” which I find somewhat inadequate, although I have heard rather muffled recordings in some interactive multimedia induction courses as well.


But wait, there’s more! While we usually don’t get to hear those two sounds short of being involved in a fire drill or an actual fire, this unit actually has a reportoire of 32-tones. Now I could just buy this unit for $45.40 today, but that’s not inexpensive for a hobby interest. I wouldn’t really have a genuine use for it beyond occasionally scaring the heck out of my neighbours and deafening myself over time with those sweet tones.


Sounds are powerful and sometimes, even beautiful. Functional sounds like these are rarely celebrated, nor are they really noticed. They become part of our landscape, for our “occasional” hearing. But these sounds were likely designed with purpose – to cut through the noise, to be clear, salient, and to provoke a sense of urgency and unease. They were designed to save lives, perhaps draw attention to something, or in some cases, to repel vandals.


I wanted to hear the sounds that these sounders (and others) can make, in as good of a fidelity as I could, preferably without needing to buy them. Having lived in Australia most of my life, I can really only say that I’ve heard less than a handful of them. The units also have a long heritage with rather simple-to-generate tone sequences that have a distinct, harsher, hard-keyed character that seems lost in some of the newer “voice” sounders with MP3 playback capability. There are also legacy tones which are no longer part of current standards which may be worth hearing again. I decided to do some research and call upon good ol’ math and Python to make it a reality.


Research


Sounders are used in a variety of applications including fire safety, burglar alarms and industrial process audio alerting roles. The tones used in fire safety are often governed by national and international standards which are numerous and rarely freely accessible.


Rather than pursue that route, I decided to go with looking at what the sounder manufacturers had to offer. The market appears to be dominated by Eaton, of which Fulleon is a subsidiary, with sub-brands such as Asserta, Roshni, Squashni and X10; and Klaxon which has sub-brands of Sonos (not the Wi-Fi speaker company) and Nexus. I did discover a few other companies making sounders, but most of them are “voice” sounders (i.e. pure audio) and not tone-based.


Thankfully, it turns out the datasheets and installers manuals for a range of these sounders provide some specifications about the tones they can emit – here are the most useful tables I found:



Looking closer, it seems the Asserta’s 42-tone library is fully covered by the X10’s 102-tone library. The 32-tone libraries of the Roshni and Sonos are mostly, but not all, covered by the X10 and similarly, the 60-tone Nexus also has some differences.


Some of these differences appear to be “genuine” while others could be down to poor notation. For example, does x/y Hz at 1Hz mean 500ms of each or 1000ms of each? Is the assumption of 50/50 duty-cycle valid? What about phase – which tone comes first? The Asserta datasheet seems to go against the others especially regarding which tone comes first in its documentation. I suspect this is down to “synchronisation” – the tone which comes first needs to be standardised to ensure all sounders go off in the same pattern at the same time to prevent confusion, but the way it is noted in the datasheet makes it somewhat ambiguous as to which duration is for which tone, so I decided to avoid using it entirely.


It is also noted that sometimes there appears to be duplicated tones. This is because of the way some of the older sounders are configured – namely, they are set for their primary tone and a “2nd stage” tone is tied to it. This way, you would configure the Australian pre-evacuate tone (for example) as the primary tone and when the 2nd-stage input is triggered, the matching Australian evacuate tone would play instead. But because the 2nd-stage tones were not independently configurable, choosing the first tone chose the pair, hence the need for duplication. Later units offered some independent selections and some modern voice sounders even go up to 5-stages independent based on MP3 files!


Before I go forward, I will acknowledge that I did discover Eaton has their own tone library page which has video samples of their sounder’s outputs, but I wasn’t too pleased with it. The samples were short, sometimes they weren’t very clear, occasionally they had glitches and the audio compression really didn’t make me feel like I was “in the room”. I guess I wanted my “lo-fi” tones done “hi-fi”.


Coding Methodology


I decided to make this a weekend project – no nice code, no comments, just pure hackery.


To make it quick and simple, I decided to use Python 3 without anything fancy – no numpy because I probably didn’t need it. I decided to use the inbuilt wave library to write .wav files, math because I’ll be doing a lot of sin and 2π the old-fashioned way, struct to mash the data into the right endianness/length and time just because I wanted to know how long the program took.


I started with simple functions for single tones, then another for interrupted tones. As more complex functions started to grow, I realised some functions were supersets of others, so I converted those functions to call those superset functions with the necessary parameters to generate equivalent output. It wasn’t until sweeps that I had to do some real head-scratching, working out how to make a constant-phase chirp. Then came interrupted-sweeps, bidirectional sweeps and T3-tone timing.


Once I had the generation side working, I had to code-in all the tone tables and then make some compromises. These included:



  • If it wasn’t a tone specified with a set of frequencies and times, I wasn’t going to generate it. Sorry no “simulated bell” and “hooter”.

  • If it had x/y Hz alternating at z Hz, then it is assumed a 50/50 duty cycle is taken with x as the leading tone and where a cycle involves the length of time for both tones.

  • If it had x-y Hz chirp at z ms, then it is assumed the time represents the time for the full chirp. In the case of a bidirectional chirp, then this is the time for just the up-sweep or just the down-sweep with a full cycle taking 2*z ms.

  • Phase continuity at change points is not guaranteed. This can cause subtle “clicks” in the output audio – but it does add the harsh character that I do like.

  • There is no envelope to tones coming on and off – they’re either there or they aren’t. This can make transitions particularly harsh – again, something I do like as it makes it clean and snappy.

  • There is no distortion
Comments 
In Channel
loading
00:00
00:00
x

0.5x

0.8x

1.0x

1.25x

1.5x

2.0x

3.0x

Sleep Timer

Off

End of Episode

5 Minutes

10 Minutes

15 Minutes

30 Minutes

45 Minutes

60 Minutes

120 Minutes

Project: Generate High-Quality Industrial Fire/Alarm Sounder Audio with Python

Project: Generate High-Quality Industrial Fire/Alarm Sounder Audio with Python

lui_gough