|
6 | 6 | //! There is also a convenience function `play` for using that output mixer to |
7 | 7 | //! play a single sound. |
8 | 8 | use crate::common::{assert_error_traits, ChannelCount, SampleRate}; |
9 | | -use crate::decoder; |
10 | 9 | use crate::math::nz; |
11 | | -use crate::mixer::{mixer, Mixer, MixerSource}; |
| 10 | +use crate::mixer::{mixer, Mixer}; |
12 | 11 | use crate::sink::Sink; |
| 12 | +use crate::{decoder, Source}; |
13 | 13 | use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; |
14 | | -use cpal::{BufferSize, Sample, SampleFormat, StreamConfig}; |
| 14 | +use cpal::{BufferSize, Sample, SampleFormat, StreamConfig, I24}; |
15 | 15 | use std::fmt; |
16 | 16 | use std::io::{Read, Seek}; |
17 | 17 | use std::marker::Sync; |
@@ -462,128 +462,58 @@ impl OutputStream { |
462 | 462 | }) |
463 | 463 | } |
464 | 464 |
|
465 | | - fn init_stream<E>( |
| 465 | + fn init_stream<S, E>( |
466 | 466 | device: &cpal::Device, |
467 | 467 | config: &OutputStreamConfig, |
468 | | - mut samples: MixerSource, |
| 468 | + mut samples: S, |
469 | 469 | error_callback: E, |
470 | 470 | ) -> Result<cpal::Stream, StreamError> |
471 | 471 | where |
| 472 | + S: Source + Send + 'static, |
472 | 473 | E: FnMut(cpal::StreamError) + Send + 'static, |
473 | 474 | { |
474 | | - let sample_format = config.sample_format; |
475 | | - let config = config.into(); |
476 | | - |
477 | | - match sample_format { |
478 | | - cpal::SampleFormat::F32 => device.build_output_stream::<f32, _, _>( |
479 | | - &config, |
480 | | - move |data, _| { |
481 | | - data.iter_mut() |
482 | | - .for_each(|d| *d = samples.next().unwrap_or(0f32)) |
483 | | - }, |
484 | | - error_callback, |
485 | | - None, |
486 | | - ), |
487 | | - cpal::SampleFormat::F64 => device.build_output_stream::<f64, _, _>( |
488 | | - &config, |
489 | | - move |data, _| { |
490 | | - data.iter_mut() |
491 | | - .for_each(|d| *d = samples.next().map(Sample::from_sample).unwrap_or(0f64)) |
492 | | - }, |
493 | | - error_callback, |
494 | | - None, |
495 | | - ), |
496 | | - cpal::SampleFormat::I8 => device.build_output_stream::<i8, _, _>( |
497 | | - &config, |
498 | | - move |data, _| { |
499 | | - data.iter_mut() |
500 | | - .for_each(|d| *d = samples.next().map(Sample::from_sample).unwrap_or(0i8)) |
501 | | - }, |
502 | | - error_callback, |
503 | | - None, |
504 | | - ), |
505 | | - cpal::SampleFormat::I16 => device.build_output_stream::<i16, _, _>( |
506 | | - &config, |
507 | | - move |data, _| { |
508 | | - data.iter_mut() |
509 | | - .for_each(|d| *d = samples.next().map(Sample::from_sample).unwrap_or(0i16)) |
510 | | - }, |
511 | | - error_callback, |
512 | | - None, |
513 | | - ), |
514 | | - cpal::SampleFormat::I32 => device.build_output_stream::<i32, _, _>( |
515 | | - &config, |
516 | | - move |data, _| { |
517 | | - data.iter_mut() |
518 | | - .for_each(|d| *d = samples.next().map(Sample::from_sample).unwrap_or(0i32)) |
519 | | - }, |
520 | | - error_callback, |
521 | | - None, |
522 | | - ), |
523 | | - cpal::SampleFormat::I64 => device.build_output_stream::<i64, _, _>( |
524 | | - &config, |
525 | | - move |data, _| { |
526 | | - data.iter_mut() |
527 | | - .for_each(|d| *d = samples.next().map(Sample::from_sample).unwrap_or(0i64)) |
528 | | - }, |
529 | | - error_callback, |
530 | | - None, |
531 | | - ), |
532 | | - cpal::SampleFormat::U8 => device.build_output_stream::<u8, _, _>( |
533 | | - &config, |
534 | | - move |data, _| { |
535 | | - data.iter_mut().for_each(|d| { |
536 | | - *d = samples |
537 | | - .next() |
538 | | - .map(Sample::from_sample) |
539 | | - .unwrap_or(u8::MAX / 2) |
540 | | - }) |
541 | | - }, |
542 | | - error_callback, |
543 | | - None, |
544 | | - ), |
545 | | - cpal::SampleFormat::U16 => device.build_output_stream::<u16, _, _>( |
546 | | - &config, |
547 | | - move |data, _| { |
548 | | - data.iter_mut().for_each(|d| { |
549 | | - *d = samples |
550 | | - .next() |
551 | | - .map(Sample::from_sample) |
552 | | - .unwrap_or(u16::MAX / 2) |
553 | | - }) |
554 | | - }, |
555 | | - error_callback, |
556 | | - None, |
557 | | - ), |
558 | | - cpal::SampleFormat::U32 => device.build_output_stream::<u32, _, _>( |
559 | | - &config, |
560 | | - move |data, _| { |
561 | | - data.iter_mut().for_each(|d| { |
562 | | - *d = samples |
563 | | - .next() |
564 | | - .map(Sample::from_sample) |
565 | | - .unwrap_or(u32::MAX / 2) |
566 | | - }) |
567 | | - }, |
568 | | - error_callback, |
569 | | - None, |
570 | | - ), |
571 | | - cpal::SampleFormat::U64 => device.build_output_stream::<u64, _, _>( |
572 | | - &config, |
573 | | - move |data, _| { |
574 | | - data.iter_mut().for_each(|d| { |
575 | | - *d = samples |
576 | | - .next() |
577 | | - .map(Sample::from_sample) |
578 | | - .unwrap_or(u64::MAX / 2) |
579 | | - }) |
580 | | - }, |
581 | | - error_callback, |
582 | | - None, |
583 | | - ), |
584 | | - _ => return Err(StreamError::UnsupportedSampleFormat), |
| 475 | + let cpal_config = config.into(); |
| 476 | + |
| 477 | + macro_rules! build_output_streams { |
| 478 | + ($($sample_format:tt, $generic:ty);+) => { |
| 479 | + match config.sample_format { |
| 480 | + $( |
| 481 | + cpal::SampleFormat::$sample_format => device.build_output_stream::<$generic, _, _>( |
| 482 | + &cpal_config, |
| 483 | + move |data, _| { |
| 484 | + data.iter_mut().for_each(|d| { |
| 485 | + *d = samples |
| 486 | + .next() |
| 487 | + .map(Sample::from_sample) |
| 488 | + .unwrap_or(<$generic>::EQUILIBRIUM) |
| 489 | + }) |
| 490 | + }, |
| 491 | + error_callback, |
| 492 | + None, |
| 493 | + ), |
| 494 | + )+ |
| 495 | + _ => return Err(StreamError::UnsupportedSampleFormat), |
| 496 | + } |
| 497 | + }; |
585 | 498 | } |
586 | | - .map_err(StreamError::BuildStreamError) |
| 499 | + |
| 500 | + let result = build_output_streams!( |
| 501 | + F32, f32; |
| 502 | + F64, f64; |
| 503 | + I8, i8; |
| 504 | + I16, i16; |
| 505 | + I24, I24; |
| 506 | + I32, i32; |
| 507 | + I64, i64; |
| 508 | + U8, u8; |
| 509 | + U16, u16; |
| 510 | + // TODO: uncomment when https://github.com/RustAudio/cpal/pull/1011 is merged |
| 511 | + // U24, U24; |
| 512 | + U32, u32; |
| 513 | + U64, u64 |
| 514 | + ); |
| 515 | + |
| 516 | + result.map_err(StreamError::BuildStreamError) |
587 | 517 | } |
588 | 518 | } |
589 | 519 |
|
|
0 commit comments