void SoundOutput_DirectSound::create_sound_buffer() { WAVEFORMATEXTENSIBLE wave_format; wave_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wave_format.Format.nChannels = 2; wave_format.Format.nSamplesPerSec = mixing_frequency; wave_format.Format.nBlockAlign = get_bytes_per_sample(); wave_format.Format.nAvgBytesPerSec = wave_format.Format.nSamplesPerSec * wave_format.Format.nBlockAlign; wave_format.Format.wBitsPerSample = sizeof(float)*8; wave_format.Format.cbSize = 22; wave_format.Samples.wValidBitsPerSample = wave_format.Format.wBitsPerSample; wave_format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; wave_format.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; DSBUFFERDESC desc; desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; desc.dwBufferBytes = get_buffer_size(); desc.dwReserved = 0; desc.lpwfxFormat = &wave_format.Format; desc.guid3DAlgorithm = GUID_NULL; HRESULT err = directsound->CreateSoundBuffer(&desc, &soundbuffer, NULL); if (FAILED(err)) throw Exception("IDirectSound8::CreateSoundBuffer failed"); }
void SoundOutput_DirectSound::write_to_sound_buffer(int write_pos, const float *data, int size) { DWORD size1 = 0, size2 = 0; void *ptr1 = 0, *ptr2 = 0; HRESULT err = soundbuffer->Lock(write_pos*get_bytes_per_sample(), size*get_bytes_per_sample(), (void **) &ptr1, &size1, (void **) &ptr2, &size2, 0); if (FAILED(err)) throw Exception("IDirectSoundBuffer8::Lock failed"); char *_data = (char *) data; if (ptr1) memcpy(ptr1, _data, size1); if (ptr2) memcpy(ptr2, _data+size1, size2); err = soundbuffer->Unlock(ptr1, size1, ptr2, size2); if (FAILED(err)) throw Exception("IDirectSoundBuffer8::Unlock failed"); }
int SoundOutput_DirectSound::find_fragment_write_position() { DWORD play = 0, write = 0; HRESULT err = soundbuffer->GetCurrentPosition(&play, &write); if (FAILED(err)) throw Exception("IDirectSoundBuffer8::GetCurrentPosition failed"); int fragment_index = ((play/get_bytes_per_sample() + frag_size + frag_size/2) / frag_size) % get_fragment_count(); return fragment_index * frag_size; }
static int channel_thread(int args, void *argp) { volatile int bufidx = 0; int channel = *(int*)argp; int i, j; unsigned short *ptr_m; unsigned int *ptr_s; void *bufptr; unsigned int samples; pl_snd_callback callback; pl_snd_channel_info *ch_info; ch_info = &sound_stream[channel]; for (j = 0; j < 2; j++) memset(ch_info->sample_buffer[j], 0, ch_info->samples[j] * get_bytes_per_sample(channel)); while (!sound_stop) { callback = ch_info->callback; bufptr = ch_info->sample_buffer[bufidx]; samples = ch_info->samples[bufidx]; if (callback && !ch_info->paused) /* Use callback to fill buffer */ callback(bufptr, samples, ch_info->user_data); else { /* Fill buffer with silence */ if (ch_info->stereo) for (i = 0, ptr_s = bufptr; i < samples; i++) *(ptr_s++) = 0; else for (i = 0, ptr_m = bufptr; i < samples; i++) *(ptr_m++) = 0; } /* Play sound */ play_blocking(channel, ch_info->left_vol, ch_info->right_vol, bufptr); /* Switch active buffer */ bufidx = (bufidx ? 0 : 1); } sceKernelExitThread(0); return 0; }
void SoundOutput_DirectSound::set_notify_positions() { int num_fragments = get_fragment_count(); if (num_fragments > 0) { std::vector<DSBPOSITIONNOTIFY> notify_positions; for (int i=0; i<num_fragments; i++) { DSBPOSITIONNOTIFY notify; notify.dwOffset = i*frag_size*get_bytes_per_sample(); notify.hEventNotify = sleep_event; notify_positions.push_back(notify); } HRESULT result = notify->SetNotificationPositions(num_fragments, ¬ify_positions[0]); if (FAILED(result)) throw Exception("IDirecTsoundNotify::SetNotificationPositions failed"); } }
int write_to_alsa(const void *buf, unsigned int size) { int ret = 0; while (size > 0) { ret = snd_pcm_writei(playback_handle, buf, size); if (ret == -EAGAIN) continue; if (ret < 0) { if (xrun_recover(ret) < 0) { fprintf(stderr, "alsa write error: (%s)\n", snd_strerror(ret)); break; } } buf += audio_channels * get_bytes_per_sample(audio_format) * ret; size -= ret; } return ret; }
int SoundOutput_DirectSound::get_buffer_size() const { return frag_size * get_bytes_per_sample() * get_fragment_count(); }
int pl_snd_init(int sample_count, int stereo) { int i, j, failed; sound_stop = 0; sound_ready = 0; /* Check sample count */ if (sample_count <= 0) sample_count = DEFAULT_SAMPLES; sample_count = PL_SND_ALIGN_SAMPLE(sample_count); pl_snd_channel_info *ch_info; for (i = 0; i < AUDIO_CHANNELS; i++) { ch_info = &sound_stream[i]; ch_info->sound_ch_handle = -1; ch_info->thread_handle = -1; ch_info->left_vol = VOLUME_MAX; ch_info->right_vol = VOLUME_MAX; ch_info->callback = NULL; ch_info->user_data = NULL; ch_info->paused = 1; ch_info->stereo = stereo; for (j = 0; j < 2; j++) { ch_info->sample_buffer[j] = NULL; ch_info->samples[j] = 0; } } /* Initialize buffers */ for (i = 0; i < AUDIO_CHANNELS; i++) { ch_info = &sound_stream[i]; for (j = 0; j < 2; j++) { if (!(ch_info->sample_buffer[j] = (short*)malloc(sample_count * get_bytes_per_sample(i)))) { free_buffers(); return 0; } ch_info->samples[j] = sample_count; } } /* Initialize channels */ for (i = 0, failed = 0; i < AUDIO_CHANNELS; i++) { sound_stream[i].sound_ch_handle = sceAudioOutOpenPort(PSP2_AUDIO_OUT_PORT_TYPE_MAIN, sample_count, 48000, (stereo) ? PSP2_AUDIO_OUT_MODE_STEREO : PSP2_AUDIO_OUT_MODE_MONO); if (sound_stream[i].sound_ch_handle < 0) { failed = 1; break; } } if (failed) { for (i = 0; i < AUDIO_CHANNELS; i++) { if (sound_stream[i].sound_ch_handle != -1) { sceAudioOutReleasePort(sound_stream[i].sound_ch_handle); sound_stream[i].sound_ch_handle = -1; } } free_buffers(); return 0; } sound_ready = 1; char label[16]; strcpy(label, "audiotX"); for (i = 0; i < AUDIO_CHANNELS; i++) { label[6] = '0' + i; sound_stream[i].thread_handle = sceKernelCreateThread(label, (void*)&channel_thread, 0x10000100, 0x10000, 0, 0, NULL); if (sound_stream[i].thread_handle < 0) { sound_stream[i].thread_handle = -1; failed = 1; break; } if (sceKernelStartThread(sound_stream[i].thread_handle, sizeof(i), &i) != 0) { failed = 1; break; } } if (failed) { sound_stop = 1; for (i = 0; i < AUDIO_CHANNELS; i++) { if (sound_stream[i].thread_handle != -1) { //sceKernelWaitThreadEnd(sound_stream[i].threadhandle,NULL); sceKernelDeleteThread(sound_stream[i].thread_handle); } sound_stream[i].thread_handle = -1; } sound_ready = 0; free_buffers(); return 0; } return sample_count; }