Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find most dominant audio frequency in sample

I'm trying to create a project that pulls in a live stream audio file from the internet and continuously samples the audio looking for the most dominant frequency for a given time period. The idea is that if it detects a frequency of let's say 440Hz over a period of time (a few seconds) that means that a particular tone was played on the live stream. Once it detects a particular tone I'll have it do some other stuff in the program. The live stream is either talking, a single tone, or silence.

I was able to do this and got a proof of concept working reading a file I generated from an online tone generator. When I pass in that file it correctly identifies the frequency (it's off by only 1 or 2 Hz). When I pull in the live stream I get frequency data that's something like: 17704Hz. My guess is that it's from the "noise" of the live stream.

I'm using the npm modules node-pitchfinder and audio-analyer to do most of the processing

Any ideas on how to get a single tone?

const fs = require('fs');
const fsa = require('fs-extra');
const Lame     = require('lame');
const Speaker  = require('speaker');
const Volume   = require('pcm-volume');
const Analyser = require('audio-analyser')
const request  = require('request')
const Chunker  = require('stream-chunker');
const { YIN } = require('node-pitchfinder')
const detectPitch = YIN({ sampleRate: 44100})
//const BUFSIZE  = 64;
const BUFSIZE  = 500;


var decoder   = new Lame.Decoder(); 
decoder.on('format', function(format){onFormat(format)});

var chunker  = Chunker(BUFSIZE);
chunker.pipe(decoder);  




var options = {
    url: 'http://relay.broadcastify.com/fq85hty701gnm4z.mp3',
    headers: {
        "Upgrade-Insecure-Requests": 1,
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15"
    }
}
var audio_stream = request(options);
//var audio_stream = fs.createReadStream('./2000.mp3');

audio_stream.pipe(chunker);

function onFormat(format)
{
    //if (volume == "undefined")
    volume = 1.0;

    vol      = new Volume(volume);
    speaker  = new Speaker(format);


    analyser = createAnalyser(format);
    analyser.on('data', sample);

    console.log(format);
    vol.pipe(speaker);  
    vol.pipe(analyser); 
    decoder.pipe(vol);
    vol.setVolume(volume);
}




function createAnalyser(format)
{
    return new Analyser({
        fftSize: 8,
            bufferSize: BUFSIZE,
            'pcm-stream': {
            channels: format.channels,
            sampleRate: format.sampleRate,
            bitDepth: format.bitDepth
        }
    });
}


var logFile = 'log.txt';
var logOptions = {flag: 'a'};

function sample()
{

    if (analyser) {

        const frequency = detectPitch(analyser._data)
        console.log(frequency)
    }
}
like image 908
Bill Avatar asked Dec 08 '18 15:12

Bill


1 Answers

You may need to:

  • Apply a Noise Reduction effect to filter out the noise from the audio source (take a look at noise-gate package)

  • Use compressor and/or limiter to optimize your sound before treatment (take a look at audio-object

Before audio signal treatment.

like image 60
A STEFANI Avatar answered Sep 28 '22 22:09

A STEFANI