|
|
|
@ -3,8 +3,17 @@
@@ -3,8 +3,17 @@
|
|
|
|
|
//! The NDSP service is used to handle communications to the DSP processor present on the console's motherboard.
|
|
|
|
|
//! Thanks to the DSP processor the program can play sound effects and music on the console's built-in speakers or to any audio device
|
|
|
|
|
//! connected via the audio jack.
|
|
|
|
|
//!
|
|
|
|
|
//! To use NDSP audio, you will need to dump DSP firmware from a real 3DS using
|
|
|
|
|
//! something like [DSP1](https://www.gamebrew.org/wiki/DSP1_3DS).
|
|
|
|
|
//!
|
|
|
|
|
//! `libctru` expects to find it at `sdmc:/3ds/dspfirm.cdc` when initializing the NDSP service.
|
|
|
|
|
#![doc(alias = "audio")] |
|
|
|
|
|
|
|
|
|
// As a result of requiring DSP firmware to initialize, all of the doctests in
|
|
|
|
|
// this module are `no_run`, since Citra doesn't provide a stub for the DSP firmware:
|
|
|
|
|
// https://github.com/citra-emu/citra/issues/6111
|
|
|
|
|
|
|
|
|
|
pub mod wave; |
|
|
|
|
use std::cell::{RefCell, RefMut}; |
|
|
|
|
use std::default::Default; |
|
|
|
@ -113,12 +122,12 @@ impl Ndsp {
@@ -113,12 +122,12 @@ impl Ndsp {
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// This function will return an error if an instance of the [`Ndsp`] struct already exists
|
|
|
|
|
/// or if there are any issues during initialization.
|
|
|
|
|
/// or if there are any issues during initialization (for example, DSP firmware
|
|
|
|
|
/// cannot be found. See [module documentation](super::ndsp) for more details.).
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -158,8 +167,7 @@ impl Ndsp {
@@ -158,8 +167,7 @@ impl Ndsp {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -190,8 +198,7 @@ impl Ndsp {
@@ -190,8 +198,7 @@ impl Ndsp {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -215,8 +222,7 @@ impl Channel<'_> {
@@ -215,8 +222,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -238,8 +244,7 @@ impl Channel<'_> {
@@ -238,8 +244,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -261,8 +266,7 @@ impl Channel<'_> {
@@ -261,8 +266,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -285,8 +289,7 @@ impl Channel<'_> {
@@ -285,8 +289,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -309,8 +312,7 @@ impl Channel<'_> {
@@ -309,8 +312,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -346,8 +348,7 @@ impl Channel<'_> {
@@ -346,8 +348,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -374,8 +375,7 @@ impl Channel<'_> {
@@ -374,8 +375,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -399,8 +399,7 @@ impl Channel<'_> {
@@ -399,8 +399,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -425,8 +424,7 @@ impl Channel<'_> {
@@ -425,8 +424,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # use std::default::Default;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
@ -450,8 +448,7 @@ impl Channel<'_> {
@@ -450,8 +448,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -476,8 +473,7 @@ impl Channel<'_> {
@@ -476,8 +473,7 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// #
|
|
|
|
@ -506,11 +502,10 @@ impl Channel<'_> {
@@ -506,11 +502,10 @@ impl Channel<'_> {
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # #![feature(allocator_api)]
|
|
|
|
|
/// # use std::error::Error;
|
|
|
|
|
/// # fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// #
|
|
|
|
|
/// # use ctru::linear::LinearAllocator;
|
|
|
|
|
/// use ctru::services::ndsp::wave::Wave;
|
|
|
|
@ -518,10 +513,10 @@ impl Channel<'_> {
@@ -518,10 +513,10 @@ impl Channel<'_> {
|
|
|
|
|
/// let ndsp = Ndsp::new()?;
|
|
|
|
|
/// let mut channel_0 = ndsp.channel(0)?;
|
|
|
|
|
///
|
|
|
|
|
/// # let _audio_data = Box::new_in([0u8; 96], LinearAllocator);
|
|
|
|
|
/// # let audio_data = Box::new_in([0u8; 96], LinearAllocator);
|
|
|
|
|
///
|
|
|
|
|
/// // Provide your own audio data.
|
|
|
|
|
/// let mut wave = Wave::new(_audio_data, AudioFormat::PCM16Stereo, false);
|
|
|
|
|
/// let mut wave = Wave::new(audio_data, AudioFormat::PCM16Stereo, false);
|
|
|
|
|
///
|
|
|
|
|
/// // Clear the audio queue and stop playback.
|
|
|
|
|
/// channel_0.queue_wave(&mut wave);
|
|
|
|
|