Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to do live analysis on mic #4

Open
konsumer opened this issue Jun 28, 2019 · 5 comments
Open

Trying to do live analysis on mic #4

konsumer opened this issue Jun 28, 2019 · 5 comments

Comments

@konsumer
Copy link

konsumer commented Jun 28, 2019

Hi, I am attempting to get live analysis on mic-input. I am running this code:

const fs = require('fs')
const { MusicBeatDetector, MusicBeatScheduler, MusicGraph } = require('music-beat-detector')
const { AudioIO, SampleFormat16Bit, getDevices } = require('naudiodon')

console.log(getDevices())

const musicGraph = new MusicGraph()
const ws = fs.createWriteStream('rawAudio.raw')

const ai = new AudioIO({
  inOptions: {
    channelCount: 2,
    sampleFormat: SampleFormat16Bit,
    sampleRate: 44100,
    deviceId: -1 // Use -1 or omit the deviceId to select the default device
  }
})

const musicBeatScheduler = new MusicBeatScheduler(pos => {
  console.log(`peak at ${pos}ms`) // your music effect goes here
})

const musicBeatDetector = new MusicBeatDetector({
  plotter: musicGraph.getPlotter(),
  scheduler: musicBeatScheduler.getScheduler()
})

ai.start()

ai
  .pipe(musicBeatDetector.getAnalyzer())
  .on('peak-detected', (pos, bpm) => console.log(`peak-detected at ${pos}ms, detected bpm ${bpm}`))
  .on('end', () => {
    fs.writeFileSync('graph.svg', musicGraph.getSVG())
    console.log('end')
  })

  .pipe(ws)
  .on('open', () => musicBeatScheduler.start())

When I run it on a mac, I get an audio-file with a single beat, and an SVG with same data:

graph

Screen Shot 2019-06-28 at 12 05 43 PM

I get this error after a single beat (seems to be calling my callbacks each once):

[ { id: 0,
    name: 'Built-in Microphone',
    maxInputChannels: 2,
    maxOutputChannels: 0,
    defaultSampleRate: 44100,
    defaultLowInputLatency: 0.0029478458049886623,
    defaultLowOutputLatency: 0.01,
    defaultHighInputLatency: 0.01310657596371882,
    defaultHighOutputLatency: 0.1,
    hostAPIName: 'Core Audio' },
  { id: 1,
    name: 'Built-in Output',
    maxInputChannels: 0,
    maxOutputChannels: 2,
    defaultSampleRate: 44100,
    defaultLowInputLatency: 0.01,
    defaultLowOutputLatency: 0.010997732426303855,
    defaultHighInputLatency: 0.1,
    defaultHighOutputLatency: 0.021156462585034015,
    hostAPIName: 'Core Audio' },
  { id: 2,
    name: 'Loopback Audio',
    maxInputChannels: 2,
    maxOutputChannels: 2,
    defaultSampleRate: 44100,
    defaultLowInputLatency: 0.01,
    defaultLowOutputLatency: 0.0014512471655328798,
    defaultHighInputLatency: 0.1,
    defaultHighOutputLatency: 0.011609977324263039,
    hostAPIName: 'Core Audio' } ]
PortAudio V19.6.0-devel, revision unknown
Input audio options: default device, sample rate 44100, channels 2, bits per sample 16, max queue 2
Input device name is Built-in Microphone
AudioIO: portAudio status - input overflow
AudioIO end
end

Any hints what I am doing wrong?

@konsumer
Copy link
Author

konsumer commented Jun 28, 2019

Actually, this code makes my callbacks get called just once, above quits before it gets to them:

const fs = require('fs')
const { MusicBeatDetector, MusicBeatScheduler, MusicGraph } = require('music-beat-detector')
const { AudioIO, SampleFormat16Bit, getDevices } = require('naudiodon')

console.log(getDevices())

const musicGraph = new MusicGraph()
const ws = fs.createWriteStream('rawAudio.raw')

const ai = new AudioIO({
  inOptions: {
    channelCount: 2,
    sampleFormat: SampleFormat16Bit,
    sampleRate: 44100,
    deviceId: -1 // Use -1 or omit the deviceId to select the default device
  }
})

const musicBeatScheduler = new MusicBeatScheduler(pos => {
  console.log(`peak at ${pos}ms`) // your music effect goes here
})

const musicBeatDetector = new MusicBeatDetector({
  plotter: musicGraph.getPlotter(),
  scheduler: musicBeatScheduler.getScheduler()
})

ai
  .pipe(musicBeatDetector.getAnalyzer())
  .on('peak-detected', (pos, bpm) => console.log(`peak-detected at ${pos}ms, detected bpm ${bpm}`))
  .on('end', () => {
    fs.writeFileSync('graph.svg', musicGraph.getSVG())
    console.log('end')
  })

  .pipe(ws)

ai.start()
musicBeatScheduler.start()

changing the order of the start calls doesn't seem to help.

@konsumer
Copy link
Author

As a sidenote, this records a raw file fine:

const fs = require('fs')
const { AudioIO, SampleFormat16Bit } = require('naudiodon')

const ws = fs.createWriteStream('rawAudio.raw')

const ai = new AudioIO({
  inOptions: {
    channelCount: 2,
    sampleFormat: SampleFormat16Bit,
    sampleRate: 44100,
    deviceId: -1 // Use -1 or omit the deviceId to select the default device
  }
})

ai.pipe(ws)
ai.start()

@konsumer
Copy link
Author

konsumer commented Jun 28, 2019

I thought maybe I should wait for the mic to be ready, so I used this code, which did same (detected up until first beat, then quit with AudioIO: portAudio status - input overflow):

const fs = require('fs')
const { AudioIO, SampleFormat16Bit } = require('naudiodon')
const { MusicBeatDetector, MusicBeatScheduler, MusicGraph } = require('music-beat-detector')

const musicGraph = new MusicGraph()

const musicBeatScheduler = new MusicBeatScheduler(pos => {
  console.log(`peak at ${pos}ms`) // your music effect goes here
})

const musicBeatDetector = new MusicBeatDetector({
  plotter: musicGraph.getPlotter(),
  scheduler: musicBeatScheduler.getScheduler()
})

const ws = fs.createWriteStream('rawAudio.raw')

const ai = new AudioIO({
  inOptions: {
    channelCount: 2,
    sampleFormat: SampleFormat16Bit,
    sampleRate: 44100,
    deviceId: -1 // Use -1 or omit the deviceId to select the default device
  }
})

ai
  .pipe(musicBeatDetector.getAnalyzer())
  .on('peak-detected', (pos, bpm) => console.log(`peak-detected at ${pos}ms, detected bpm ${bpm}`))
  .pipe(ws)
  .on('ready', () => musicBeatScheduler.start())
  .on('end', () => {
    fs.writeFileSync('graph.svg', musicGraph.getSVG())
    console.log('end')
  })
ai.start()

Screen Shot 2019-06-28 at 12 19 11 PM

graph

@konsumer
Copy link
Author

konsumer commented Jun 28, 2019

Also, if you know of another way to beat-analyze mic input, I'm not stuck on this method. Basically, I am trying to accomplish "fire my callback when a beat is detected from mic". If you follow this issue, I tried mic-stream, first, with same issues (it was less chatty about overflow, but it exited after 1 beat.)

@lucdetellis
Copy link

Solution here: konsumer/tplink-lightbulb#35 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants