10. Sound

The CTR-SDK sound library controls sound playback by communicating with the components loaded by the DSP library. The sound library comes with 24 voice objects. An application can allocate the required number of voice objects from this selection and then play back sounds by registering a wave buffer (information about sound source data).

Figure 10-1. How Sound-Related Libraries Interact

DSP Library SND Library Voice WaveBuffer ChannelCount SampleFormat SampleRate Pitch Priority State MixParam Volume MasterVolume Status Data DefaultComponent DspCycles SyncObject status loopFlag userParam bufferAddress sampleLength Component Send Allocate Append Signal pAdpcmContext Member [R/W] Member [Read] next Id Class/Structure Member [Write] Member [Hidden] AdpcmParam InterpolationType AuxReturnVolume AuxCallback

10.1. Initialization

You must use the DSP library to play back sound on the system. Consequently, before initializing the SND library used for sound playback, you must initialize the DSP library and load the components for sound playback.

Use the nn::dsp::Initialize() function to initialize the DSP library, and then use the nn::dsp::LoadDefaultComponent() function to load the components for sound playback.

Call the nn::snd::Initialize() function to initialize the SND library.

Code 10-1. Initializing the DSP and SND Libraries
nn::Result result;
result = nn::dsp::Initialize();
result = nn::dsp::LoadDefaultComponent();
result = nn::snd::Initialize(); 

10.1.1. Setting the Number of Output Buffers

You can use the nn::snd::SetOutputBufferCount() function to specify the number of output buffers for the sound data that is ultimately output from the DSP.

Code 10-2. Setting the Number of Output Buffers
void nn::snd::SetOutputBufferCount(s32 count);
s32 nn::snd::GetOutputBufferCount(); 

You can specify a count of either 2 or 3. The default is 2.

Two output buffers minimize the delay until sound data is actually played, but sound may break up if there are delays in sound thread processing.

Three output buffers cause sound to be delayed by approximately five milliseconds more than two output buffers, but they also prevent sound from breaking up when there are slight delays in the sound thread.

This function clears the content of the output buffers. Call it immediately after the library is initialized or at another time when sound is not being played.

You can get the current setting with the nn::snd::GetOutputBufferCount() function.

10.2. Allocating Voice Objects

The SND library synthesizes and then plays sounds on the basis of the information about the sound source data bound to the library's 24 voice objects. In other words, the library can play sounds from up to 24 sound sources at the same time.

Voice objects are limited resources. An application must use the nn::snd::AllocVoice() function to allocate voice objects to bind to the sound source data for playback.

Code 10-3. Allocating Voice Objects
nn::snd::Voice* nn::snd::AllocVoice(
        s32 priority, nn::snd::VoiceDropCallbackFunc callback, uptr userArg); 

The priority parameter specifies the priority of the voice object to allocate in the range from 0 to nn::snd::VOICE_PRIORITY_NODROP (0x7FFF = 32767). The higher the value, the higher the priority. If you specify a value outside of this range, an assert fails and processing halts.

Specifying a value for priority changes the behavior of the function when the maximum number of voice objects has already been allocated.

When priority is set to nn::snd::VOICE_PRIORITY_NODROP and the lowest-priority allocated voice objects are also nn::snd::VOICE_PRIORITY_NODROP, voice object allocation fails and the function returns NULL. For any other value, the lowest-priority allocated voice object is dropped. Attempting to allocate a lowest-priority voice object will fail.

The callback parameter specifies the callback function to be called after the library forcibly drops a voice object. No callback occurs when this value is NULL. The userArg parameter specifies any arguments to be passed to the callback. Specify NULL if this is not needed.

The types of the callback functions are defined as follows.

Code 10-4 Voice Object Drop Callback Function
typedef void (* VoiceDropCallbackFunc)(nn::snd::Voice *pVoice, uptr userArg); 

The pVoice parameter takes a pointer to the dropped voice object, and the userArg parameter takes any arguments specified at allocation.

10.2.1. Dropped-Voice Mode

The SND library releases (drops) low-priority voice objects when an attempt is made to allocate more than the maximum number of voice objects and when internal DSP processing is in danger of increasing.

Two modes exist to control this latter restriction; you can use the nn::snd::SetVoiceDropMode() function to configure them.

Code 10-5 Setting the Dropped-Voice Mode
void nn::snd::SetVoiceDropMode(nn::snd::VoiceDropMode mode); 

When mode is VOICE_DROP_MODE_DEFAULT, only predicted values are used to determine whether to drop voice objects.

When mode is VOICE_DROP_MODE_REAL_TIME, both predicted values and the actual processing load are used to determine whether to drop voice objects. You must configure three output buffers to be used when you set this mode.

10.3. Setting Sound Source Data Information

The memory region (buffer region) for storing sound source data must be allocated as a contiguous 32-byte-aligned region in device memory. The buffer region must be 32-byte aligned and sized to a multiple of 32 bytes. When allocating sound source data buffers from this region, buffers must be contiguous memory regions and the starting addresses must be 32-byte aligned, but the 32-byte multiple size restriction does not apply.

In some cases, sound source data written to a buffer might only be written to the cache. Be sure to call the nn::snd::FlushDataCache() function to write the data to memory.

Pass the sound source data to the DSP as an nn::snd::WaveBuffer sound source data information structure. Sound source data information must be initialized with the nn::snd::InitializeWaveBuffer function before configuring information about the sound source data. This is also the case when reusing information about sound source data that has already been played.

After initializing the sound source data, set the following member variables: bufferAddress for the starting address of the buffer, sampleLength for the sample length, and loopFlag for marking whether to loop playback. Specify the DSP ADPCM sample format using the pAdpcmContext member variable. You can specify a value of your own choosing for the user parameter (userParam). Do not change the values of the other members of this structure.

Set other information about the sound source data (number of channels, sample format, sampling rate, and basic information about ADPCM parameters) in the voice object.

Use the nn::snd::Voice::SetChannelCount() function to set the number of channels. Set this number to 1 for monaural data, and 2 for stereo data. Any other values are invalid.

Use the nn::snd::Voice::SetSampleFormat() function to set the sample format. The SND library supports 8-bit, 16-bit PCM, and DSP ADPCM formats.

Table 10-1. List of Sample Formats

Value

Type

Stereo Playback

SAMPLE_FORMAT_PCM8

8-bit PCM

Interleaved

SAMPLE_FORMAT_PCM16

16-bit PCM

Interleaved

SAMPLE_FORMAT_ADPCM

DSP ADPCM

No

When the sample format is DSP ADPCM, set the ADPCM parameters using the nn::snd::Voice::SetAdpcmParam() function. Set the nn::snd::WaveBuffer member variable pAdpcmContext to the address of the ADPCM context data structure stored in the sound source data, and do not change the context data until after playback has finished.

Use the nn::snd::Voice::SetSampleRate() function to set the sampling rate. Use the frequency of the sound source data.

Use the nn::snd::Voice::SetInterpolationType() function to set the method of interpolating the sound data. Use the nn::snd::Voice::GetInterpolationType() function to get the current setting. Three interpolation methods are supported, as shown in the following table. The default value is INTERPOLATION_TYPE_POLYPHASE.

Table 10-2. List of Interpolation Methods

Value

Interpolation Method

INTERPOLATION_TYPE_POLYPHASE

Interpolation using four points. The optimal coefficients are chosen based on the specified sampling rate and pitch.

INTERPOLATION_TYPE_LINEAR

Linear interpolation.

INTERPOLATION_TYPE_NONE

No interpolation. Noise occurs in the sound played back when the sound source data sampling frequency is not 32,728 Hz.

After setting all the information about the sound source, use the nn::snd::Voice::AppendWaveBuffer() function to register the sound source to the voice object. Multiple sound sources can be registered consecutively, but 4 is the maximum number of sound sources that can be played back by one voice object in one sound frame (roughly 4.889 ms).

Use the nn::snd::WaveBuffer member variable Status to check the state of a sound source after registration. This state is STATUS_FREE before a voice object is registered, STATUS_WAIT while waiting for playback, STATUS_PLAY during playback, and STATUS_DONE after playback has finished. Sound source data is managed by the voice object when in STATUS_WAIT and STATUS_PLAY, so do not change any settings when in these states.

You can modify a registered sound source by calling nn::snd::Voice::UpdateWaveBuffer. However, the only information that can be modified is the sample length (sampleLength) and loop specification flag (loopFlag). Additionally, depending on when the data is updated using SendParameterToDsp, data after the specified sample length might be played back, or modifications might be invalid because playback is already completed.

You can delete a registered sound source by calling nn::snd::Voice::DeleteWaveBuffer. Do not overwrite this data by using SendParameterToDsp to update the data until playback is complete.

For streaming playback of DSP ADPCM sound source data, you only have to set the pAdpcmContext member variable of the first sound source data registered to the voice object. The context is not updated for sound source data registered later if their pAdpcmContext member variables are set to NULL.

10.4. Creating Sound Threads

Design your application to create threads (sound threads) and have the threads wait for notifications from the DSP library to the SND library. Notifications occur roughly every 4.889 ms. Set the priority of the created threads as high as possible and avoid any intensive processing within the threads to keep sound playback from being interrupted.

Basically, what sound threads do is loop the following processes.

  1. The sound thread waits for notification from the DSP library using the nn::snd::WaitForDspSync() function.
  2. The application checks the state of the sound source data information registered to the allocated voice object. After playback has finished, it registers the next sound source data information for playback using the nn::snd::Voice::AppendWaveBuffer() function. When doing so it normally only registers the sound source data information within the sounds thread, while another thread has already loaded the sound source data to be used for sound playback into a buffer.
  3. The sound thread calls the nn::snd::SendParameterToDsp() function to send any parameters that have changed since the previous notification and any newly registered sound source data information to the DSP to update sound playback.

 

Warning:

Functions that manipulate voice objects are not thread-safe, with the exception of nn::snd::AllocVoice and nn::snd::FreeVoice. You must ensure mutual exclusion (for example, by using a critical section) when calling these functions by threads other than the sound thread.

10.5. Sound Playback

Starting, stopping, and pausing sound playback is carried out by changing the state of a voice object. Use the nn::snd::Voice::SetState and nn::snd::Voice::GetState() functions to set and get the voice object state. Set the state to STATE_PLAY to start playback, STATE_STOP to stop playback, and STATE_PAUSE to pause playback.

Table 10-3. Voice Object States

State

Description

STATE_PLAY

Order to start sound playback or an indication that playback is underway.

STATE_STOP

Order to stop sound playback or an indication that playback is stopped.

STATE_PAUSE

Order to pause sound playback or an indication that playback is paused. Set the state to STATE_PLAY to resume playback.

State changes may not be applied immediately. There may be a slight lag until parameters are sent by the nn::snd::SendParameterToDsp() function (in other words, until the sound frame update period (roughly 4.889 ms) has passed).

There are various other playback settings aside from states.

Priority

Use the nn::snd::Voice::SetPriority() function to set the priority of a voice object. Use the nn::snd::Voice::GetPriority function to get the current setting. Sounds are played in the order of voice object priority (for objects of the same priority, the most recently allocated object is played first), so there is a chance that low-priority voice objects might not be played if the processing load is too great.

Master Volume

The master volume is the overall volume for the SND library. Use the nn::snd::SetMasterVolume() function to set this. Set to a value of 1.0 to play sounds at their normal volume. Call the nn::snd::GetMasterVolume() function to get the current setting.

Volume

Represents the volume for each voice object. Use the nn::snd::Voice::SetVolume() function to set the volume. Use the nn::snd::Voice::GetVolume() function to get the current setting. Set the volume to 1.0 to specify unity gain.

Mix Parameters

Mix parameters control the gain for four channels (FrontLeft/FrontRight/RearLeft/RearRight).

Use the nn::snd::Voice::SetMixParam() function to set these parameters. Use the nn::snd::Voice::GetMixParam function to get the current settings. The gain values for the left and right channels are stored in the members of the nn::snd::MixParam structure. Set the gain to 1.0 to play the channel at its normal volume.

The sound playback volume is the product of the master volume, volume, and mix parameter values.

Pitch

Pitch is the speed applied to the sampling rate of the sound source data. Use the nn::snd::Voice::SetPitch() function to set the pitch. Use the nn::snd::Voice::GetPitch function to get the current setting. Set the pitch to 1.0 to play the data at its normal rate. Setting the pitch to 0.5 for sound source data with a sampling rate of 32 kHz would cause it to play at 16 kHz.

Checking

Use the nn::snd::Voice::IsPlaying() function to check whether a sound is currently playing.

Use the nn::snd::Voice::GetPlayPosition() function to get the current playback position. The value that is returned indicates the starting position (measured in the number of samples) in main memory of the next value that will be processed by the DSP.

AUX Buses

The two AUX buses (A and B) can be used to apply effects like delay to the sounds being played. To set and get the volume of the AUX buses, call nn::snd::SetAuxReturnVolume() and nn::snd::GetAuxReturnVolume(), respectively. Set the volume to 1.0 to specify unity gain. Because the mix parameters contain members for setting the gain of the AUX buses, you can adjust the audio data that is sent to the AUX buses for each channel independently.

To apply an effect to sounds on the AUX buses, set a callback function for each bus. Set callbacks using nn::snd::RegisterAuxCallback, and clear callbacks using nn::snd::ClearAuxCallback. To get the callback that is currently set, call nn::snd::GetAuxCallback. The types of the callback functions are defined as follows.

Code 10-6. Callback Functions for AUX Buses
typedef void(*AuxCallback)(nn::snd::AuxBusData* data, s32 sampleLength,
                           uptr userData); 

The sampling length (not the size in bytes) is passed into the sampleLength parameter, and the sound data is passed into the data parameter. Buffer addresses are set for each channel; by overwriting the data in these buffers, you can play sound data with effects applied as the output from the AUX buses.

Voice Interpolation

You can set the interpolation method used when converting from the sound source data’s sampling rate to the desired playback frequency. Call the nn::snd::Voice::SetInterpolationType or nn::snd::Voice::GetInterpolationType() functions to set or get the interpolation method.

You can set the interpolation method to the default four-point (INTERPOLATION_TYPE_POLYPHASE), linear (INTERPOLATION_TYPE_LINEAR), or none (INTERPOLATION_TYPE_NONE). With four-point interpolation, the library chooses the optimal coefficients based on the sampling rate and pitch.

Filters

You can apply a filter to each voice object. Call the nn::snd::Voice::SetFilterType or nn::snd::Voice::GetFilterType to set or get the filter setting. You can set the filter to monopolar (FILTER_TYPE_MONOPOLE), bipolar (FILTER_TYPE_BIQUAD), or the default (FILTER_TYPE_NONE). There are also functions for setting the coefficients for each filter.

Call the nn::snd::Voice::SetMonoFilterCoefficients or nn::snd::Voice::GetMonoFilterCoefficients() functions to set or get the monopolar filter coefficients. Even if you don’t alter the coefficients, you can specify a cutoff frequency to act as a monopolar low-pass filter.

Call the nn::snd::Voice::SetBiquadFilterCoefficients or nn::snd::Voice::SetBiquadFilterCoefficients() functions to set or get the bipolar filter coefficients. This filter type only allows the coefficients to be specified.

When setting using coefficients, calculate the coefficients for each filter using a base frequency of 32,728 Hz.

Clipping Mode

Any portion of the final sound output that exceeds 16 bits is clipped. Two clipping methods are used: either normal clipping or soft clipping that reduces high-frequency noise. Call the nn::snd::SetClippingMode to set the clipping mode. Specify either CLIPPING_MODE_NORMAL or CLIPPING_MODE_SOFT. Call the nn::snd::GetClippingMode() function to get the current setting. Soft clipping is the default clipping mode.

The sound output is clipped non-linearly when using soft clipping, which reduces distortion, but this also corrects sample values that are not at the maximum amplitude. This has almost no effect on normal music and most other audio, but harmonics such as single-frequency sine waves may be added for sound input.

The following figure shows the waveforms for a high-amplitude sine wave after clipping in each mode. The green shows the results of soft clipping.

Figure 10-2. Clipping Mode Differences

amplitude Normal Clip Soft Clip tim [sample]

Automatic Fade-In

You can automatically fade in audio from a volume of 0 at the start of playback to the previously set volume over the course of a single sound frame. You can set fade-in processing for each voice object using the nn::snd::Voice::SetStartFrameFadeInFlag() function, passing true as the argument to enable fade-in. The default is false (no fade-in).

Using BCWAV Files

Use the SetupBcwav() function of the nn::snd::Voice class to easily use the waveform files converted by the ctr_WaveConverter tool (BCWAV files) for sound playback.

Code 10-7. Using BCWAV Files
bool nn::snd::Voice::SetupBcwav(uptr addrBcwav,
  nn::snd::WaveBuffer* pWaveBuffer0, nn::snd::WaveBuffer* pWaveBuffer1,
  nn::snd::Bcwav::ChannelIndex channelIndex = nn::snd::Bcwav::CHANNEL_INDEX_L); 

For the addrBcwav parameter, specify the starting address of a buffer to load the bcwav file to. The data loaded into the buffer is used (as is) as the sound source data, so the buffer is also subject to the requirements for sound source data. Specifically, the memory must be in device memory with the starting address 32-byte aligned, the buffer size must be a multiple of 32 bytes, and the loaded data must be written to memory using the nn::snd::FlushDataCache() function.

For the pWaveBuffer0 and pWaveBuffer1 parameters, specify pointers to the nn::snd::WaveBuffer structures used for initial and loop playback. The structures must be created by the application. If you know that the sound source does not have a loop flag set, you can pass NULL to the pWaveBuffer1 parameter.

For the channelIndex parameter, when using stereo sound source data, specify which channel’s sound source data to allocate to the Voice class. When using monaural sound source data, you must specify CHANNEL_INDEX_L for this parameter. In the current version, stereo sound source data converted by the ctr_WaveConverter tool is not interleaved. Consequently, you must prepare two instances of the Voice class to play stereo BCWAV files.

The function returns true if successful and the data is prepared for playback. Of the parameters not included in the BCWAV file header, values of 1.0 are used as the defaults for the volume and pitch. Mix parameters are not set.

Use the nn::snd::Bcwav class to access BCWAV file header information.

Effects (Delay and Reverb)

You can apply effects to sound playback by either implementing effects in your application by using an AUX bus callback function, or by using the effects provided by the library.

The SND library provides delay (nn::snd::FxDelay class) and reverb (nn::snd::FxReverb class) effects. To use them, generate an instance of the appropriate class, set the effect parameters, allocate working memory, and then call the nn::snd::SetEffect() function, specifying the effect instance and the AUX bus to apply the effect to. You can only apply one type of effect per bus, and if you call SetEffect multiple times, only the effect from the last call is applied. The CPU rather than the DSP handles the actual effect processing.

To stop using an effect, call the nn::snd::ClearEffect() function, specifying the AUX bus to clear. This function only clears effects, and does not cancel any AUX bus callback function.

Note:

For more information about the effect parameters, see the API Reference.

10.5.1. Sound Output Mode

The SND library provides three sound output modes: mono, stereo, and surround. Call nn::snd::SetSoundOutputMode to set the output mode and nn::snd::GetSoundOutputMode to get the current setting.

Code 10-8. Sound Output Mode Definitions and Getter/Setter Functions
typedef enum
{
    OUTPUT_MODE_MONO       = 0,
    OUTPUT_MODE_STEREO     = 1,
    OUTPUT_MODE_3DSURROUND = 2
} nn::snd::OutputMode;

bool nn::snd::SetSoundOutputMode(nn::snd::OutputMode mode);
nn::snd::OutputMode nn::snd::GetSoundOutputMode(void); 

If nn::snd::SetSoundOutputMode returns true, the operation succeeded, and the sound output mode is set to the value specified by the mode parameter. By default, the sound output mode is set to stereo (OUTPUT_MODE_STEREO).

10.5.1.1. Mono

The mix that is output through the left and right speakers is as follows. The four input channels (FrontLeft, FrontRight, RearLeft, and RearRight) are the result of mixing the outputs of all voices with the output of the AUX buses.

Output = ( FrontLeft + FrontRight + RearLeft + RearRight ) * 0.5

10.5.1.2. Stereo

The mixes that are output through the left and right speakers are as follows. The four input channels (FrontLeft, FrontRight, RearLeft, and RearRight) are the result of mixing the outputs of all voices with the output of the AUX buses.

OutputLeft = ( FrontLeft + RearLeft )

OutputRight = ( FrontRight + RearRight )

10.5.1.3. Surround

The four input channels (FrontLeft, FrontRight, RearLeft, and RearRight) undergo 3D surround processing to impart spatial widening to the output. The four input channels are the result of mixing the outputs of all voices with the output of the AUX buses. This 3D surround operation calculates the speaker output based on the "position" and "depth" parameters of the virtual speakers. Although the 3D surround operation is performed on the mixed output (as opposed to individual voices), it is possible to bypass the output of the front channels (FrontLeft and FrontRight) on a per-voice basis so that they are not affected by the 3D surround operation.

After 3D surround processing, sound volume tends to seem greater when the pan position is set on either left or right edges compared to when set in the center. If this difference in volume is a concern, correct output accordingly to mitigate the effect, such as by limiting the left and right edge mix parameters to a maximum of roughly 0.8.

Positions of the Virtual Speakers

Use nn::snd::SetSurroundSpeakerPosition to specify the virtual speaker position mode. If this function succeeds in setting the mode, it returns true.

Code 10-9. Setting the Virtual Speaker Position
bool nn::snd::SetSurroundSpeakerPosition(nn::snd::SurroundSpeakerPosition pos); 

Specify one of the following modes for the pos parameter.

Table 10-4. Modes for the Virtual Speaker Position

Setting Value

Description

SURROUND_SPEAKER_POSITION_SQUARE

Square mode. Positions the virtual speakers in a square pattern.

SURROUND_SPEAKER_POSITION_WIDE

Wide mode. Positions the left and right virtual speakers further apart.

The virtual speaker mode determines the angle of symmetry of the four channels. The following figure shows the angles at which the speakers are positioned for each mode.

Figure 10-3. Virtual Speaker Placement for Each Mode

FrontLeft FrontRight RearLeft RearRight Center 45° 135° 60° 110° SURROUND_SPEAKER_POSITION_SQUARE SURROUND_SPEAKER_POSITION_WIDE Listening Position

Surround Depth

You can vary the intensity of the surround effect by specifying a depth value using nn::snd::SetSurroundDepth. If this function succeeds in setting the depth value, it returns true.

Code 10-10. Setting the Surround Depth Value
bool nn::snd::SetSurroundDepth(f32 depth); 

Set the depth parameter to a value between 0.0 and 1.0, inclusive. Specifying 0.0 produces the minimum effect, and specifying 1.0 produces the maximum effect. The default value is currently 1.0.

The 3D surround operation automatically adapts depending on whether the sound is being output through the speakers or through headphones. This depth value is only valid when sound is output through the speakers. It is disabled when sound is output through the headphones and has no effect on the surround effect.

Front Bypass Setting

The output for the rear channels is always affected by the 3D surround operation. In contrast, each voice object that is output to the front channels can be configured on an individual basis to bypass the 3D surround effect. You can configure the bypass setting by calling the SetFrontBypassFlag member function of the nn::snd::Voice class.

Code 10-11. Front Bypass Setting for Voice Objects
void nn::snd::Voice::SetFrontBypassFlag(bool flag); 

Set the flag parameter to true to make the output for the front channels bypass the 3D sound operation. This argument defaults to false (in which case, the data for the front channels does not bypass the 3D surround operation).

Figure 10-4. Effect of the Front Bypass Setting on the 3D Surround Operation

Voice Bypass 3D Surround Front Rear true false Output

You can also set the front bypass for the front channel of the AUX bus.

Code 10-12. Setting the AUX Bus Front Bypass
bool nn::snd::SetAuxFrontBypass(nn::snd::AuxBusId busId, bool flag); 

Specify the AUX bus ID in the busId parameter, and pass true in the flag parameter to bypass. The default value for all buses is false (no bypass).

10.5.2. Headphone Connection State

Call the nn::snd::GetHeadphoneStatus or nn::snd::UpdateHeadphoneStatus() function to find out whether headphones are connected to the audio jack. The function returns true when headphones are connected.

The GetHeadphoneStatus() function returns the headphone state from the states regularly updated by the SendParameterToDsp() function called by the sound thread, and so the results may be up to 32 sound frames (approximately 160 ms) old. Use the UpdateHeadphoneStatus() function if you need real-time results. Note that this function entails a heavier processing load, as it updates the DSP state.

Code 10-13. Headphone Connection State
bool nn::snd::GetHeadphoneStatus();
bool nn::snd::UpdateHeadphoneStatus(); 

10.5.3. Getting the Output Audio Data

You can load the mixed audio data that will ultimately be played back through the speakers into a buffer.

Code 10-14. Getting the Output Audio Data
bool nn::snd::GetMixedBusData(s16* pData, 
                              s32 nSamplesPerFrame = NN_SND_SAMPLES_PER_FRAME); 

For the pData parameter, specify a buffer for storing the audio data. The buffer’s starting address must be nn::snd::MIXED_BUS_DATA_ALIGNMENT (4 bytes) aligned. Calculate the required size of the buffer as sizeof(s16) * nSamplesPerFrame * 2.

For the nSamplesPerFrame parameter, specify the number of samples per channel (usually NN_SND_SAMPLES_PER_FRAME).

The function returns true if it successfully loads the audio data. Audio data is stored in stereo 16-bit PCM format, with the left and right channels interleaved. Header information is not included. The sampling rate is the sound DSP sampling rate (approximately 32,728 Hz).

10.5.4. Encoding to DSP ADPCM Format

Call the nn::snd::EncodeAdpcmData() function to encode monaural 16-bit PCM data in the DSP ADPCM format.

Code 10-15. Encoding to DSP ADPCM Format
s32 nn::snd::GetAdpcmOutputBufferSize(s32 nSamples);
void nn::snd::EncodeAdpcmData(s16* pInput, u8* pOutput, s32 nSamples, 
                              s32 sampleRate, s32 loopStart, s32 loopEnd, 
                              nn::snd::DspsndAdpcmHeader* pInfo); 

For the pInput parameter, specify the starting address of a buffer storing the monaural 16-bit PCM data to encode. The function can only encode monaural audio data. Specify the number of samples and the sampling rate in the nSamples and sampleRate parameters.

For the pOutput parameter, specify a buffer for storing the encoded DSP ADPCM data. The buffer’s starting address must be 4-byte aligned. Get the required size of the buffer by calling the nn::snd::GetAdpcmOutputBufferSize() function, passing the number of audio data samples as an argument.

For the loopStart and loopEnd parameters, specify the starting and ending sample positions for looping. Specify sample position values relative to the start of the 16-bit PCM data, which is considered as 0.

For the pInfo parameter, specify a pointer to a structure storing the DSP ADPCM data header information.

10.5.5. Decoding From DSP ADPCM Format

Call the nn::snd::DecodeAdpcmData() function to decode audio data in the DSP ADPCM format to monaural 16-bit CPM data.

Code 10-16. Decoding From DSP ADPCM Format
void nn::snd::DecodeAdpcmData(const u8* pInput, s16* pOutput, 
                              const nn::snd::AdpcmParam& param, 
                              nn::snd::AdpcmContext& context, s32 nSamples); 

For the pInput parameter, specify the starting address of a buffer storing the DSP ADPCM data to decode. For the param and context parameters, specify the DSP ADPCM data parameters and context. For the nSamples parameter, specify the number of audio data samples.

For the pOutput parameter, specify a buffer for storing the decoded monaural 16-bit PCM data. The buffer’s starting address must be 4-byte aligned.

After execution completes, context stores the context as of the end of decoding.

10.5.6. Converting Between Sample Positions and Nibbles

The library provides functions for converting between PCM data sample positions and the number of DSP ADPCM nibbles.

Code 10-17. Converting Between Sample Positions and Nibbles
u32 nn::snd::ConvertAdpcmPos2Nib(u32 nPos);
u32 nn::snd::ConvertAdpcmNib2Pos(u32 nNib); 

10.5.7. Sound Output When the System Is Closed and Sleep Is Rejected

If sleep is rejected when the system is closed, sound is forcibly output to the headphones, but you can control that behavior with the following function.

Code 10-18. Controlling Sound Output When the System Is Closed and Sleep Is Rejected
nn::Result nn::snd::SetHeadphoneOutOnShellClose(bool forceout); 

Specify false for the forceout argument to have sound output from the speakers even when the system is closed (if the headphones are not connected). Specify true to have sound output from the headphones regardless of whether the headphones are connected.

Warning:

If you specify false for the forceout argument, make sure to reject the request to sleep. If the request is not rejected, sound is output from the speakers in the time between when the system is closed and when it transitions to the sleep state.

If this function is called from within the callback function that receives the sleep request, however, that particular sleep request does not change the setting, and the setting takes effect starting with the next sleep request.

10.5.8. Source of Noise and Countermeasures

The device design may cause noise in the following circumstances.

10.5.8.1. A buzzing noise comes from the speaker

The speaker and physical structure of CTR has shown a tendency for clipping noise to occur around 500 Hz. This noise is caused by the surround process amplifying the playback when playing a sound containing the 500-Hz range with a pan.

It occurs under the following conditions.

  • The speaker is playing sound.
  • The playback is a sine wave in the 400-Hz to 600-Hz range, or a sine wave like sound, such as a flute or French horn.
  • The volume is set to a high value.
  • The pan is set to the maximum value.
  • Surround is ON.

Possible ways of handling this include:

  • Do not pan across extremes.
  • Center the playback, and maintain the volume by playing back in moderate volume from the two speakers.
  • Suppress the 400-Hz to 600-Hz range using the equalizer.
  • Change the tone (waveform) of the playback.

10.5.8.2. A mechanical buzzing noise comes from the speaker

This noise, which is caused by the vibration from loud playback, is transmitted to the 3D depth slider. The 3D depth slider and the body rattle against one another other.

This noise becomes most noticeable with a simple sine wave tone in the 400-Hz to 1-kHz range. This noise is conclusively identified by holding down the 3D depth slider with a finger. The noise is this type if the buzzing is muted by the pressure on the slider.

This noise is mitigated by reducing the speaker output volume, or playing a sound that is not a simple sine wave tone.

10.5.8.3. Light static sound is superimposed on the playback

This noise is caused by the design of the speaker.

This noise is somewhat prominent in single tones using sine waves at about 400 Hz to 1 kHz.

This noise is mitigated by reducing the speaker output volume, or playing a sound that is not a simple sine wave tone.

10.5.8.4. A snapping or popping noise is heard from the earphone under certain circumstances

In the following cases, a snapping or popping noise is audible from the earphones.

  • When power is turned on or off
  • When entering or leaving Sleep Mode
  • When entering compatibility mode

This noise is due to the design of the system. There is no mitigation measure. If the noise is heard when the power is turned on with the volume slider set to zero, the sound always occurs on that unit in these circumstances.

There are production and development units that cause this noise. But this noise does not occur with PARTNER-CTR.

10.6. Reusing Sound Source Data Information

Information for sound source data that has been played back can be reused by initializing with the nn::snd::InitializeWaveBuffer() function. Use the status member of the sound source data information to check whether sound source data playback has finished.

Table 10-5 Sound Source Data Information States

State

Description

STATUS_FREE

State immediately after initializing sound source data information.

STATUS_WAIT

State immediately after registering sound source data information to a voice object.

STATUS_PLAY

State when sound source data is being played.

STATUS_DONE

State when sound source data playback is finished. Includes when sound playback has been stopped.

STATUS_TO_BE_DELETED

State when registered sound source data is scheduled for deletion using nn::snd::Voice::DeleteWaveBuffer.

The state transitions to STATUS_DONE the next time nn::snd::SendParameterToDsp is executed.

The following diagram shows these state transitions.

Figure 10-5. Sound Source Data Information State Transitions

STATUS_FREE STATUS_WAIT STATUS_PLAY STATUS_DONE nn::snd::InitializeWaveBuffer() nn::snd::Voice::AppendWaveBuffer() nn::snd::Voice::SetState(STATE_PLAY) nn::snd::Voice::SetState(STATE_STOP) or Playing wave data is finished.

10.7. Releasing Voice Objects

Use the nn::snd::FreeVoice() function to release voice objects that are no longer needed. However, voice objects targeted for dropping by the library at the time of allocation must not be released using this function.

10.8. Finalizing

Complete the following steps to finalize the DSP and SND libraries used for sound playback.

  1. Call the nn::snd::Finalize() function to close the SND library.
  2. Call the nn::dsp::UnloadComponent() function to unload the components loaded into the DSP library and stop the library.
  3. Call the nn::dsp::Finalize() function to close the DSP library.
Code 10-19. Finalizing Sound Processing
nn::snd::Finalize();
nn::dsp::UnloadComponent();
nn::dsp::Finalize(); 

CONFIDENTIAL