device 0.0.4

A generative engine
use super::*;

pub(crate) struct Input {
  format: SoundFormat,
  samples: Arc<Mutex<Vec<f32>>>,
  #[allow(unused)]
  stream: Stream,
}

impl Input {
  pub(crate) fn drain(&self, min: Option<usize>) -> Option<Sound> {
    let mut samples = self.samples.lock().unwrap();

    if let Some(min) = min
      && samples.len() < min
    {
      return None;
    }

    let end = min.unwrap_or(samples.len());

    Some(Sound::new(self.format, samples.drain(..end).collect()))
  }

  pub(crate) fn format(&self) -> SoundFormat {
    self.format
  }

  pub(crate) fn new(
    device: cpal::Device,
    supported_stream_config: SupportedStreamConfig,
  ) -> Result<Self> {
    let mut stream_config = supported_stream_config.config();

    stream_config.buffer_size = match supported_stream_config.buffer_size() {
      SupportedBufferSize::Range { min, max } => {
        BufferSize::Fixed(DEFAULT_BUFFER_SIZE.clamp(*min, *max))
      }
      SupportedBufferSize::Unknown => BufferSize::Default,
    };

    let samples = Arc::new(Mutex::new(Vec::new()));

    let stream = device
      .build_input_stream(
        &stream_config,
        {
          let samples = samples.clone();
          move |data: &[f32], _: &cpal::InputCallbackInfo| {
            samples.lock().unwrap().extend(data);
          }
        },
        move |err| {
          eprintln!("input stream error: {err}");
        },
        None,
      )
      .context(error::AudioBuildInputStream)?;

    stream.play().context(error::AudioPlayStream)?;

    log::info!(
      "input stream opened: {}",
      StreamConfigDisplay(&stream_config),
    );

    Ok(Self {
      format: SoundFormat {
        channels: stream_config.channels,
        sample_rate: stream_config.sample_rate.0,
      },
      samples,
      stream,
    })
  }
}