// createDspBlock: Create a new block for DSP service void createDspBlock(ndspWaveBuf* waveBuf, u16 bps, u32 size, bool loop, u32* data){ waveBuf->data_vaddr = (void*)data; waveBuf->nsamples = size / bps; waveBuf->looping = loop; waveBuf->offset = 0; DSP_FlushDataCache(data, size); }
void Sound::play() { if (!m_buffer || m_buffer->getSampleCount() == 0) return; if (getStatus() == Playing) stop(); m_channel = 0; while (m_channel < 24 && ndspChnIsPlaying(m_channel)) m_channel++; if (m_channel == 24) { err() << "Sound::play() failed because all channels are in use." << std::endl; m_channel = -1; return; } setPlayingOffset(m_pauseOffset); if (m_pauseOffset != Time::Zero) m_pauseOffset = Time::Zero; u32 size = sizeof(Int16) * m_buffer->getSampleCount(); ndspChnReset(m_channel); ndspChnSetInterp(m_channel, NDSP_INTERP_POLYPHASE); ndspChnSetRate(m_channel, float(m_buffer->getSampleRate())); ndspChnSetFormat(m_channel, (m_buffer->getChannelCount() == 1) ? NDSP_FORMAT_MONO_PCM16 : NDSP_FORMAT_STEREO_PCM16); DSP_FlushDataCache((u8*)m_buffer->getSamples(), size); ndspChnWaveBufAdd(m_channel, &m_ndspWaveBuf); }
// High frequency square wave, PCM16 void fillBuffer(u32 *audio_buffer, size_t size) { for (size_t i = 0; i < size; i++) { u32 data; switch (i % 5) { case 0: data = 0x1000; break; case 1: data = 0x6000; break; case 2: data = 0x4000; break; case 3: data = 0x2000; break; case 4: data = 0x5000; break; } audio_buffer[i] = (data<<16) | (data&0xFFFF); } DSP_FlushDataCache(audio_buffer, size); }
//---------------------------------------------------------------------------- void fill_buffer(void *audioBuffer, size_t size) { //---------------------------------------------------------------------------- u32 *dest = (u32*)audioBuffer; stb_vorbis_get_samples_short_interleaved(vorbisFile, 2, (short*)dest, Samples * 2); DSP_FlushDataCache(audioBuffer,size); }
void playSoundChannels(int startchn, int samples, bool loop, std::vector<sample*>& data, std::vector<ndspWaveBuf>& waveBufs) { for (unsigned int i = 0; i < data.size(); i++) { int channel = startchn + i; waveBufs[i].data_vaddr = data[i]; waveBufs[i].nsamples = samples / data.size(); waveBufs[i].looping = loop; DSP_FlushDataCache(data[i], samples * sizeof(sample)); ndspChnWaveBufAdd(channel, &waveBufs[i]); } }
static void audioThreadFunc(void *arg) { Audio::MixerImpl *mixer = (Audio::MixerImpl *)arg; OSystem_3DS *osys = (OSystem_3DS *)g_system; int i; const int channel = 0; int bufferIndex = 0; const int bufferCount = 3; const int bufferSize = 80000; // Can't be too small, based on delayMillis duration const int sampleRate = mixer->getOutputRate(); int sampleLen = 0; uint32 lastTime = osys->getMillis(true); uint32 time = lastTime; ndspWaveBuf buffers[bufferCount]; for (i = 0; i < bufferCount; ++i) { memset(&buffers[i], 0, sizeof(ndspWaveBuf)); buffers[i].data_vaddr = linearAlloc(bufferSize); buffers[i].looping = false; buffers[i].status = NDSP_WBUF_FREE; } ndspChnReset(channel); ndspChnSetInterp(channel, NDSP_INTERP_LINEAR); ndspChnSetRate(channel, sampleRate); ndspChnSetFormat(channel, NDSP_FORMAT_STEREO_PCM16); while (!osys->exiting) { osys->delayMillis(100); // Note: Increasing the delay requires a bigger buffer time = osys->getMillis(true); sampleLen = (time - lastTime) * 22 * 4; // sampleRate / 1000 * channelCount * sizeof(int16); lastTime = time; if (!osys->sleeping && sampleLen > 0) { bufferIndex++; bufferIndex %= bufferCount; ndspWaveBuf *buf = &buffers[bufferIndex]; buf->nsamples = mixer->mixCallback(buf->data_adpcm, sampleLen); if (buf->nsamples > 0) { DSP_FlushDataCache(buf->data_vaddr, bufferSize); ndspChnWaveBufAdd(channel, buf); } } } for (i = 0; i < bufferCount; ++i) linearFree(buffers[i].data_pcm8); }
void N3DS_SoundCallback(void* dud) { if (N3DS_audioBuf[N3DS_soundFillBlock].status == NDSP_WBUF_DONE) { u32 flen = (N3DS_bufferSize * N3DS_sampleSize); u32 ilen = flen >> 2; u32* invbuf = (u32*) N3DS_audioBuf[N3DS_soundFillBlock].data_vaddr; if (N3DS_sound->sample_size > 1) { Sound_Callback((u8*) N3DS_audioBuf[N3DS_soundFillBlock].data_pcm8, flen); } else { Sound_Callback((u8*) N3DS_audioBuf[N3DS_soundFillBlock].data_pcm8, flen); for(int i = 0; i < ilen; i++) invbuf[i] ^= 0x80808080; } DSP_FlushDataCache(N3DS_audioBuf[N3DS_soundFillBlock].data_pcm8, flen); ndspChnWaveBufAdd(0, &N3DS_audioBuf[N3DS_soundFillBlock]); N3DS_soundFillBlock = !N3DS_soundFillBlock; }