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

Implement AnalyserNode #127

Merged
merged 7 commits into from Sep 14, 2018

Basic AnalysisEngine

  • Loading branch information
Manishearth committed Sep 14, 2018
commit 55706b4c07caadb680b388994a4439ca23d73c38
@@ -1,4 +1,4 @@
use block::{Block, Chunk};
use block::{Block, Chunk, FRAMES_PER_BLOCK_USIZE};
use node::AudioNodeEngine;
use node::BlockInfo;
use node::{AudioNodeType, ChannelInfo, ChannelInterpretation};
@@ -35,3 +35,73 @@ impl AudioNodeEngine for AnalyserNode {
inputs
}
}

/// From https://webaudio.github.io/web-audio-api/#dom-analysernode-fftsize
pub const MAX_FFT_SIZE: usize = 32768;
pub const MAX_BLOCK_COUNT: usize = MAX_FFT_SIZE / FRAMES_PER_BLOCK_USIZE;

/// The actual analysis is done on the DOM side. We provide
/// the actual base functionality in this struct, so the DOM
/// just has to do basic shimming
pub struct AnalysisEngine {
/// The number of past sample-frames to consider in the FFT
fft_size: usize,
/// This is a ring buffer containing the last MAX_FFT_SIZE
/// sample-frames
data: Box<[f32; MAX_FFT_SIZE]>,
/// The index of the current block
current_block: usize,
/// Have we computed the FFT already?
fft_computed: bool,
}

impl AnalysisEngine {
pub fn new(fft_size: usize) -> Self {
Self {
fft_size,
data: Box::new([0.; MAX_FFT_SIZE]),
current_block: MAX_BLOCK_COUNT - 1,
fft_computed: false,
}
}

fn advance(&mut self) {
self.current_block += 1;
if self.current_block >= MAX_BLOCK_COUNT {
self.current_block = 0;
}
}

/// Wrap around the index of a block `offset` elements in the past
fn block_index(&self, offset: usize) -> usize {
debug_assert!(offset < MAX_BLOCK_COUNT);
if offset > self.current_block {
MAX_BLOCK_COUNT - offset + self.current_block
} else {
self.current_block - offset
}
}

/// Get the data of a block. `offset` tells us how far back to go
fn block_mut(&mut self, offset: usize) -> &mut [f32] {
let index = FRAMES_PER_BLOCK_USIZE * self.block_index(offset);
&mut self.data[index..(index + FRAMES_PER_BLOCK_USIZE)]
}

pub fn push(&mut self, mut block: Block) {
debug_assert!(block.chan_count() == 1);
self.advance();
if !block.is_silence() {
self.block_mut(0).copy_from_slice(block.data_mut());
}
self.fft_computed = false;
}

fn compute_fft(&mut self) {
if self.fft_computed {
return;
}
self.fft_computed = true;
// ...
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.