Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  mixer.rs

  Sprache: Rust
 

use cubeb_backend::{ChannelLayout, SampleFormat};
use std::mem;
use std::os::raw::{c_int, c_void};

extern crate audio_mixer;
pub use self::audio_mixer::Channel;

const CHANNEL_ORDER: [audio_mixer::Channel; audio_mixer::Channel::count()] = [
    audio_mixer::Channel::FrontLeft,
    audio_mixer::Channel::FrontRight,
    audio_mixer::Channel::FrontCenter,
    audio_mixer::Channel::LowFrequency,
    audio_mixer::Channel::BackLeft,
    audio_mixer::Channel::BackRight,
    audio_mixer::Channel::FrontLeftOfCenter,
    audio_mixer::Channel::FrontRightOfCenter,
    audio_mixer::Channel::BackCenter,
    audio_mixer::Channel::SideLeft,
    audio_mixer::Channel::SideRight,
    audio_mixer::Channel::TopCenter,
    audio_mixer::Channel::TopFrontLeft,
    audio_mixer::Channel::TopFrontCenter,
    audio_mixer::Channel::TopFrontRight,
    audio_mixer::Channel::TopBackLeft,
    audio_mixer::Channel::TopBackCenter,
    audio_mixer::Channel::TopBackRight,
    audio_mixer::Channel::Silence,
    audio_mixer::Channel::Discrete,
];

pub fn get_channel_order(channel_layout: ChannelLayout) -> Vec<audio_mixer::Channel> {
    let mut map = channel_layout.bits();
    let mut order = Vec::new();
    let mut channel_index: usize = 0;
    while map != 0 {
        if map & 1 == 1 {
            order.push(CHANNEL_ORDER[channel_index]);
        }
        map >>= 1;
        channel_index += 1;
    }
    order
}

fn get_default_channel_order(channel_count: usize) -> Vec<audio_mixer::Channel> {
    assert_ne!(channel_count, 0);
    let mut channels = Vec::with_capacity(channel_count);
    for channel in CHANNEL_ORDER.iter().take(channel_count) {
        channels.push(*channel);
    }

    if channel_count > CHANNEL_ORDER.len() {
        channels.extend(vec![
            audio_mixer::Channel::Silence;
            channel_count - CHANNEL_ORDER.len()
        ]);
    }

    channels
}

#[derive(Debug)]
enum MixerType {
    IntegerMixer(audio_mixer::Mixer<i16>),
    FloatMixer(audio_mixer::Mixer<f32>),
}

impl MixerType {
    fn new(
        format: SampleFormat,
        input_channels: &[audio_mixer::Channel],
        output_channels: &[audio_mixer::Channel],
    ) -> Self {
        match format {
            SampleFormat::S16LE | SampleFormat::S16BE | SampleFormat::S16NE => {
                cubeb_log!("Create an integer type(i16) mixer");
                Self::IntegerMixer(audio_mixer::Mixer::<i16>::new(
                    input_channels,
                    output_channels,
                ))
            }
            SampleFormat::Float32LE | SampleFormat::Float32BE | SampleFormat::Float32NE => {
                cubeb_log!("Create an floating type(f32) mixer");
                Self::FloatMixer(audio_mixer::Mixer::<f32>::new(
                    input_channels,
                    output_channels,
                ))
            }
        }
    }

    fn sample_size(&self) -> usize {
        match self {
            MixerType::IntegerMixer(_) => mem::size_of::<i16>(),
            MixerType::FloatMixer(_) => mem::size_of::<f32>(),
        }
    }

    fn input_channels(&self) -> &[Channel] {
        match self {
            MixerType::IntegerMixer(m) => m.input_channels(),
            MixerType::FloatMixer(m) => m.input_channels(),
        }
    }

    fn output_channels(&self) -> &[Channel] {
        match self {
            MixerType::IntegerMixer(m) => m.output_channels(),
            MixerType::FloatMixer(m) => m.output_channels(),
        }
    }

    fn mix(
        &self,
        input_buffer_ptr: *const (),
        input_buffer_size: usize,
        output_buffer_ptr: *mut (),
        output_buffer_size: usize,
        frames: usize,
    ) {
        use std::slice;

        // Check input buffer size.
        let size_needed = frames * self.input_channels().len() * self.sample_size();
        assert!(input_buffer_size >= size_needed);
        // Check output buffer size.
        let size_needed = frames * self.output_channels().len() * self.sample_size();
        assert!(output_buffer_size >= size_needed);

        match self {
            MixerType::IntegerMixer(m) => {
                let in_buf_ptr = input_buffer_ptr as *const i16;
                let out_buf_ptr = output_buffer_ptr as *mut i16;
                let input_buffer = unsafe {
                    slice::from_raw_parts(in_buf_ptr, frames * self.input_channels().len())
                };
                let output_buffer = unsafe {
                    slice::from_raw_parts_mut(out_buf_ptr, frames * self.output_channels().len())
                };
                let mut in_buf = input_buffer.chunks(self.input_channels().len());
                let mut out_buf = output_buffer.chunks_mut(self.output_channels().len());
                for _ in 0..frames {
                    m.mix(in_buf.next().unwrap(), out_buf.next().unwrap());
                }
            }
            MixerType::FloatMixer(m) => {
                let in_buf_ptr = input_buffer_ptr as *const f32;
                let out_buf_ptr = output_buffer_ptr as *mut f32;
                let input_buffer = unsafe {
                    slice::from_raw_parts(in_buf_ptr, frames * self.input_channels().len())
                };
                let output_buffer = unsafe {
                    slice::from_raw_parts_mut(out_buf_ptr, frames * self.output_channels().len())
                };
                let mut in_buf = input_buffer.chunks(self.input_channels().len());
                let mut out_buf = output_buffer.chunks_mut(self.output_channels().len());
                for _ in 0..frames {
                    m.mix(in_buf.next().unwrap(), out_buf.next().unwrap());
                }
            }
        };
    }
}

#[derive(Debug)]
pub struct Mixer {
    mixer: MixerType,
    // Only accessed from callback thread.
    buffer: Vec<u8>,
}

impl Mixer {
    pub fn new(
        format: SampleFormat,
        in_channel_count: usize,
        input_layout: ChannelLayout,
        out_channel_count: usize,
        mut output_channels: Vec<audio_mixer::Channel>,
    ) -> Self {
        assert!(in_channel_count > 0);
        assert!(out_channel_count > 0);

        cubeb_log!(
            "Creating a mixer with input channel count: {}, input layout: {:?},\
             out channel count: {}, output channels: {:?}",
            in_channel_count,
            input_layout,
            out_channel_count,
            output_channels
        );

        let input_channels = if in_channel_count as u32 != input_layout.bits().count_ones() {
            cubeb_log!(
                "Mismatch between input channels and layout. Applying default layout instead"
            );
            get_default_channel_order(in_channel_count)
        } else {
            get_channel_order(input_layout)
        };

        // When having one or two channel, force mono or stereo. Some devices (namely,
        // Bose QC35, mark 1 and 2), expose a single channel mapped to the right for
        // some reason. Some devices (e.g., builtin speaker on MacBook Pro 2018) map
        // the channel layout to the undefined channels.
        if out_channel_count == 1 {
            output_channels = vec![audio_mixer::Channel::FrontCenter];
        } else if out_channel_count == 2 {
            output_channels = vec![
                audio_mixer::Channel::FrontLeft,
                audio_mixer::Channel::FrontRight,
            ];
        }

        let all_silence = vec![audio_mixer::Channel::Silence; out_channel_count];
        if output_channels.is_empty()
            || out_channel_count != output_channels.len()
            || all_silence == output_channels
            || Self::duplicate_channel_present(&output_channels)
        {
            cubeb_log!("Use invalid layout. Apply default layout instead");
            output_channels = get_default_channel_order(out_channel_count);
        }

        Self {
            mixer: MixerType::new(format, &input_channels, &output_channels),
            buffer: Vec::new(),
        }
    }

    pub fn update_buffer_size(&mut self, frames: usize) -> bool {
        let size_needed = frames * self.mixer.input_channels().len() * self.mixer.sample_size();
        let elements_needed = size_needed / mem::size_of::<u8>();
        if self.buffer.len() < elements_needed {
            self.buffer.resize(elements_needed, 0);
            true
        } else {
            false
        }
    }

    pub fn get_buffer_mut_ptr(&mut self) -> *mut u8 {
        self.buffer.as_mut_ptr()
    }

    // `update_buffer_size` must be called before this.
    pub fn mix(&self, frames: usize, dest_buffer: *mut c_void, dest_buffer_size: usize) -> c_int {
        let (src_buffer_ptr, src_buffer_size) = self.get_buffer_info();
        self.mixer.mix(
            src_buffer_ptr as *const (),
            src_buffer_size,
            dest_buffer as *mut (),
            dest_buffer_size,
            frames,
        );
        0
    }

    fn get_buffer_info(&self) -> (*const u8, usize) {
        (
            self.buffer.as_ptr(),
            self.buffer.len() * mem::size_of::<u8>(),
        )
    }

    fn duplicate_channel_present(channels: &[audio_mixer::Channel]) -> bool {
        let mut bitmap: u32 = 0;
        for channel in channels {
            if channel != &Channel::Silence && channel != &Channel::Discrete {
                if (bitmap & channel.bitmask()) != 0 {
                    return true;
                }
                bitmap |= channel.bitmask();
            }
        }
        false
    }
}

// This test gives a clear channel order of the ChannelLayout passed from cubeb interface.
#[test]
fn test_get_channel_order() {
    assert_eq!(
        get_channel_order(ChannelLayout::MONO),
        [Channel::FrontCenter]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::MONO_LFE),
        [Channel::FrontCenter, Channel::LowFrequency]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::STEREO),
        [Channel::FrontLeft, Channel::FrontRight]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::STEREO_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::LowFrequency
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::LowFrequency
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_2F1),
        [Channel::FrontLeft, Channel::FrontRight, Channel::BackCenter]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_2F1_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::LowFrequency,
            Channel::BackCenter
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F1),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::BackCenter
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F1_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::LowFrequency,
            Channel::BackCenter
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_2F2),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::SideLeft,
            Channel::SideRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_2F2_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::LowFrequency,
            Channel::SideLeft,
            Channel::SideRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::QUAD),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::BackLeft,
            Channel::BackRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::QUAD_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::LowFrequency,
            Channel::BackLeft,
            Channel::BackRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F2),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::SideLeft,
            Channel::SideRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F2_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::LowFrequency,
            Channel::SideLeft,
            Channel::SideRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F2_BACK),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::BackLeft,
            Channel::BackRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F2_LFE_BACK),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::LowFrequency,
            Channel::BackLeft,
            Channel::BackRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F3R_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::LowFrequency,
            Channel::BackCenter,
            Channel::SideLeft,
            Channel::SideRight
        ]
    );
    assert_eq!(
        get_channel_order(ChannelLayout::_3F4_LFE),
        [
            Channel::FrontLeft,
            Channel::FrontRight,
            Channel::FrontCenter,
            Channel::LowFrequency,
            Channel::BackLeft,
            Channel::BackRight,
            Channel::SideLeft,
            Channel::SideRight
        ]
    );
}

#[test]
fn test_get_default_channel_order() {
    for len in 1..CHANNEL_ORDER.len() + 10 {
        let channels = get_default_channel_order(len);
        if len <= CHANNEL_ORDER.len() {
            assert_eq!(channels, &CHANNEL_ORDER[..len]);
        } else {
            let silences = vec![audio_mixer::Channel::Silence; len - CHANNEL_ORDER.len()];
            assert_eq!(channels[..CHANNEL_ORDER.len()], CHANNEL_ORDER);
            assert_eq!(&channels[CHANNEL_ORDER.len()..], silences.as_slice());
        }
    }
}

#[test]
fn test_non_silent_duplicate_channels() {
    let duplicate = [
        Channel::FrontLeft,
        Channel::Silence,
        Channel::FrontRight,
        Channel::FrontCenter,
        Channel::Silence,
        Channel::FrontRight,
    ];
    assert!(Mixer::duplicate_channel_present(&duplicate));

    let non_duplicate = [
        Channel::FrontLeft,
        Channel::Silence,
        Channel::FrontRight,
        Channel::FrontCenter,
        Channel::Silence,
        Channel::Silence,
    ];
    assert!(!Mixer::duplicate_channel_present(&non_duplicate));

    let duplicate = [
        Channel::FrontLeft,
        Channel::Discrete,
        Channel::FrontRight,
        Channel::FrontCenter,
        Channel::Discrete,
        Channel::FrontRight,
    ];
    assert!(Mixer::duplicate_channel_present(&duplicate));

    let non_duplicate = [
        Channel::FrontLeft,
        Channel::Discrete,
        Channel::FrontRight,
        Channel::FrontCenter,
        Channel::Discrete,
        Channel::Discrete,
    ];
    assert!(!Mixer::duplicate_channel_present(&non_duplicate));
}

Messung V0.5 in Prozent
C=90 H=95 G=92

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002