Anybody know of a straightforward way to analyse the sound recordings from SAQ transmissions and plot how the frequency varies over time? πŸŽ…

#audioanalysis #sound #audiosoftware

@MW1CFN Are you wanting to do something like this: https://academo.org/demos/spectrum-analyzer/#google_vignette

?

Spectrum Analyzer | Academo.org - Free, interactive, education.

This audio spectrum analyzer enables you to see the frequencies present in audio recordings.

@jasonemiller Thanks. Not quite. I want the narrow CW tone of the radio transmissions to be isolated and its small variation in frequency over time plotted. πŸ™

@MW1CFN Got it. The link I shared demonstrated that, in a way. That piece of software took an audio file and did the spectral decomposition (FT-type processing), showing the spectrum in time.

Are you looking for more of a 'waterfall' type display where you can infer the carrier frequency and the bandwidth of the signal at any one time?

VLF Receiver Software Toolkit

A software toolkit for VLF timestamped reception, signal processing, storage and retrieval

@g0fcu Thanks! As luck would have it, my daughter's Linux laptop ("I don't want Linux", but she loved it πŸ˜‰) is becoming available...πŸ™
@jasonemiller What I want to do is plot (as a graph, rather than a waterfall per se) the single carrier frequency (around 700Hz audio) against time, thus revealing how the carrier drifted - remarkably little, given the electro-mechanical feedback system feathering a 1.25t disc of metal spinning at 2115rpm! πŸ™

@MW1CFN So. you want to determine at each time (say, second) the carrier frequency. Then you want to plot those time-frequency measurements, expecting to see a graph that is approximately horizontal. Am I understanding you correctly?

If so, then this is beyond my easy reach. Someone with more signal processing experience could probably point you to a tool. Hopefully our back-and-forth here will be helpful to other helpful souls.

@jasonemiller Yes, that's pretty much it. It's something I've been trying to look into for a while, but never managed to make any progress. Lack of ability is, admittedly, a factor, too.😭

@MW1CFN If you email me a sample audio file, I might be able to find some time to chew on it this weekend. No promises, but I learn by doing and will be happy to share with you what I learn.

Can I β€˜private mention’ you my email? Or, if you think the file will be too big for email, we can find another way to transfer the data.

@jasonemiller That's very kind of you. I've uploaded the file to Soundcloud. The signal doesn't appear for a minute or two due to the need to get a noise reference beforehand:

https://soundcloud.com/user-722868764/cut-sdruno-20240630-082507-17200hz?utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing&si=d243499349824625871adbbd43988b6e

Cut SDRuno 20240630 082507 17200HZ

SAQ VLF transmission, first of two on 30/06/2024

SoundCloud
@MW1CFN Is there a way to download a WAV or MP3 file from SoundCloud? I don't see one.
@MW1CFN You might need to enable downloading of the file.
@jasonemiller It seems it's a pay-only feature. Ah well. Another way will have to be found (300MB file size).
@MW1CFN Crisis averted. I used the 'analog hole' to grab a copy using Audio Hijak (Rogue Ameoba software). I've been chewing on the mp3 for a bit this morning already.

@MW1CFN OK. This is what I can up with after a morning and afternoon of trying to remember python.

Save this as a python script in the same directory as your recording (which is called 'recording.mp3' in this script) and run.

The standard caveats about libraries and stuff applies.

WARNING: this is a total hack. At the most best, it will suggest a way for you to get what you want.

========

```#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 06 11:08am

@author: Jason Miller (KM6PSZ)
"""

# basic idea from https://www.kaggle.com/code/vishnurapps/dummies-guide-to-audio-analysis

import librosa
import matplotlib.pyplot as plt
import warnings

import numpy as np

warnings.filterwarnings('ignore')

# load audio file as data set
# NOTE: loads file as a time series

# here
# y is the frequency value
# sr is the sampling rate from which we can inferr the sample times

yd, sr = librosa.load("recording.mp3")

# timestep
deltat=1/sr

#number of samples in the audio file
L=len(yd)

# array of sampling times
time = [ deltat*i for i in range( L )]
# array of sampling times for the zero crossing vector
time2=[time[i] for i in range (L-1)]

# grab a portion of the audio file for analysis (to keep the size managable as I
# work to pull together some code)
#
# Here we take the portion of data starting from the 20,000 index and going to the 20400 index.
time1=np.split(time, [20000,20400],axis=0)
yd1=np.split(yd, [20000,20400],axis=0)
# Here we determine which of the entries are zero crossings
logicyd=librosa.zero_crossings(yd)
logicyd1=np.split(logicyd, [20000,20400],axis=0)
# here we get the indices of the zero-crossings
zeros=np.nonzero(logicyd)

times=[time[i] for i in zeros[0]]
dtimes=2*np.diff(times)
yds=[yd[i] for i in zeros[0]]
yds=[yds[i] for i in range(len(yds)-1)]

freq=[1/dtimes[i] for i in range( len(dtimes) )]
#freqdata=librosa.util.stack([time2, freq1], axis=-1)

print(freq)

#
# # visualize the data - note that all the values are binary (either 0 or 1)
# print(logicyd1)
#
# # what follow is from
# # https://librosa.org/doc/latest/generated/librosa.zero_crossings.html#librosa.zero_crossings
#
# # here is the time-amplitude data
# data=librosa.util.stack([time1, yd1], axis=-1)
# # here are the times of the zero crossings
# time2=time1[zeros1]
# # here are the time-amplitude pairs at the zero crossings
# yd2 = data[zeros1]
# # because time for one oscillation is twice the time between two zero crossings
# # the frequency is the inverse of this
# deltazc=2*diff(time2)
# freq1=[1/deltazc[i] for i in range( len(deltazc) )]
# freqdata=librosa.util.stack([time2, freq1], axis=-1)
#
#

plt.figure(figsize=(20, 4))
plt.plot(freq)
plt.grid()
plt.title('frequencies')
plt.xlabel('time')
plt.ylabel('text')
plt.show()
```

Dummies guide to audio analysis 🧐🧐🧐

Explore and run machine learning code with Kaggle Notebooks | Using data from Cornell Birdcall Identification

EDIT: cleaned up the script a little but, and included the modified script on my post (not in Mastodon).

@MW1CFN Wrote up a quick post on this 'shitty first draft' script. People can find it here and make their own improvements.

If an improved script is shared, I'll post it on my obscure site that nobody looks and an Google probably doesn't know how to index.

http://www.jasonemiller.org/2024/07/06/CW-and-zero-crossing.html

Calculating CW frequencies from Audio

EDIT: cleaned up the script a tiny bit.

Home Page of Jason E. Miller, Ph.D.
@jasonemiller Thanks so much! I'll have a play a little later and report back πŸ™