SoundManager::SoundManager(QString soundDirectory) { QString applicationDirectory; QString completeSoundDirectory; char cwd[PATH_MAX]; // Initialize ALUT. if (alutInit(NULL, NULL) == false) { reportALUTError(alutGetError()); } // Get the complete application directory in which we will load sounds from. // We convert to QString since it is more convenient when working with directories. getcwd(cwd, PATH_MAX); applicationDirectory = QString(cwd); // Append the assets directory and the actual sounds directory name. completeSoundDirectory = applicationDirectory .append("/app/native/assets/") .append(soundDirectory); // Create OpenAL buffers from all files in the sound directory. QDir dir(completeSoundDirectory); if (!dir.exists()) { qDebug() << "Cannot find the sounds directory." << completeSoundDirectory; } else { // Set a filter for file listing, only files should be listed. dir.setFilter(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot); // Get a directory listing. QFileInfoList list = dir.entryInfoList(); // Traverse and load all the audio files into buffers. for (int i = 0; i < list.size(); ++i) { // Create a file info for each audio file. QFileInfo fileInfo = list.at(i); const char* path = fileInfo.absoluteFilePath().toStdString().c_str(); ALenum error; // Generate buffers to hold audio data. alGenBuffers(1, &mSoundBuffers[fileInfo.fileName()]); error = alGetError(); if (error != AL_NO_ERROR) { reportOpenALError(error); break; } // Load sound file. FILE* file = fopen(path, "rb"); if (!file) { qDebug() << "Failed to load audio file " << path; break; } // Read the file header char header[12]; ALuint bufferId = mSoundBuffers[fileInfo.fileName()]; if (fread(header, 1, 12, file) != 12) { qDebug() << "Invalid header for audio file " << path; alDeleteBuffers(1, &bufferId); goto cleanup; } // Check the file format & load the buffer with audio data. if (memcmp(header, "RIFF", 4) == 0) { if (!loadWav(file, bufferId)) { qDebug() << "Invalid wav file: " << path; alDeleteBuffers(1, &bufferId); goto cleanup; } } else if (memcmp(header, "OggS", 4) == 0) { if (!loadOgg(file, bufferId)) { qDebug() << "Invalid ogg file: " << path; alDeleteBuffers(1, &bufferId); goto cleanup; } } else { qDebug() << "Unsupported audio file: " << path; goto cleanup; } cleanup: if (file) { fclose(file); } } } // Generate a number of sources used to attach buffers and play. alGenSources(SOUNDMANAGER_MAX_NBR_OF_SOURCES, mSoundSources); ALenum error = alGetError(); if (error != AL_NO_ERROR) { reportOpenALError(error); } }
int main (int argc, const char * argv[]) { MyLoopPlayer player; // convert to an OpenAL-friendly format and read into memory CheckError(loadLoopIntoBuffer(&player), "Couldn't load loop into buffer") ; // set up OpenAL buffer ALCdevice* alDevice = alcOpenDevice(NULL); CheckALError ("Couldn't open AL device"); // default device ALCcontext* alContext = alcCreateContext(alDevice, 0); CheckALError ("Couldn't open AL context"); alcMakeContextCurrent (alContext); CheckALError ("Couldn't make AL context current"); ALuint buffers[1]; alGenBuffers(1, buffers); CheckALError ("Couldn't generate buffers"); alBufferData(*buffers, AL_FORMAT_MONO16, player.sampleBuffer, player.bufferSizeBytes, player.dataFormat.mSampleRate); // AL copies the samples, so we can free them now free(player.sampleBuffer); // set up OpenAL source alGenSources(1, player.sources); CheckALError ("Couldn't generate sources"); alSourcei(player.sources[0], AL_LOOPING, AL_TRUE); CheckALError ("Couldn't set source looping property"); alSourcef(player.sources[0], AL_GAIN, AL_MAX_GAIN); CheckALError("Couldn't set source gain"); updateSourceLocation(player); CheckALError ("Couldn't set initial source position"); // connect buffer to source alSourcei(player.sources[0], AL_BUFFER, buffers[0]); CheckALError ("Couldn't connect buffer to source"); // set up listener alListener3f (AL_POSITION, 0.0, 0.0, 0.0); CheckALError("Couldn't set listner position"); // ALfloat listenerOrientation[6]; // 3 vectors: forward x,y,z components, then up x,y,z // listenerOrientation[2] = -1.0; // listenerOrientation[0] = listenerOrientation [1] = 0.0; // listenerOrientation[3] = listenerOrientation [4] = listenerOrientation[5] = 0.0; // alListenerfv (AL_ORIENTATION, listenerOrientation); // start playing // alSourcePlayv (1, player.sources); alSourcePlay(player.sources[0]); CheckALError ("Couldn't play"); // and wait printf("Playing...\n"); time_t startTime = time(NULL); do { // get next theta updateSourceLocation(player); CheckALError ("Couldn't set looping source position"); CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); } while (difftime(time(NULL), startTime) < RUN_TIME); // cleanup: alSourceStop(player.sources[0]); alDeleteSources(1, player.sources); alDeleteBuffers(1, buffers); alcDestroyContext(alContext); alcCloseDevice(alDevice); printf ("Bottom of main\n"); }
void SoundStream::Stream() { // Create the buffers ALCheck(alGenBuffers(BufferCount, myBuffers)); for (int i = 0; i < BufferCount; ++i) myEndBuffers[i] = false; // Fill the queue bool requestStop = FillQueue(); // Play the sound ALCheck(alSourcePlay(mySource)); while (myIsStreaming) { // The stream has been interrupted! if (SoundSource::GetStatus() == Stopped) { if (!requestStop) { // Just continue ALCheck(alSourcePlay(mySource)); } else { // End streaming myIsStreaming = false; } } // Get the number of buffers that have been processed (ie. ready for reuse) ALint nbProcessed = 0; ALCheck(alGetSourcei(mySource, AL_BUFFERS_PROCESSED, &nbProcessed)); while (nbProcessed--) { // Pop the first unused buffer from the queue ALuint buffer; ALCheck(alSourceUnqueueBuffers(mySource, 1, &buffer)); // Find its number unsigned int bufferNum = 0; for (int i = 0; i < BufferCount; ++i) if (myBuffers[i] == buffer) { bufferNum = i; break; } // Retrieve its size and add it to the samples count if (myEndBuffers[bufferNum]) { // This was the last buffer: reset the sample count mySamplesProcessed = 0; myEndBuffers[bufferNum] = false; } else { ALint size, bits; ALCheck(alGetBufferi(buffer, AL_SIZE, &size)); ALCheck(alGetBufferi(buffer, AL_BITS, &bits)); mySamplesProcessed += size / (bits / 8); } // Fill it and push it back into the playing queue if (!requestStop) { if (FillAndPushBuffer(bufferNum)) requestStop = true; } } // Leave some time for the other threads if the stream is still playing if (SoundSource::GetStatus() != Stopped) Sleep(10); } // Stop the playback ALCheck(alSourceStop(mySource)); // Unqueue any buffer left in the queue ClearQueue(); // Delete the buffers ALCheck(alSourcei(mySource, AL_BUFFER, 0)); ALCheck(alDeleteBuffers(BufferCount, myBuffers)); }
bool ttLibC_AlPlayer_queue(ttLibC_AlPlayer *player, ttLibC_PcmS16 *pcmS16) { if(player == NULL) { return false; } if(pcmS16 == NULL) { return false; } ttLibC_AlPlayer_ *player_ = (ttLibC_AlPlayer_ *)player; switch(pcmS16->type) { case PcmS16Type_bigEndian: case PcmS16Type_bigEndian_planar: case PcmS16Type_littleEndian_planar: default: ERR_PRINT("non support pcm type."); player_->inherit_super.error = ttLibC_updateError(Target_On_Util, Error_InvalidOperation); return false; case PcmS16Type_littleEndian: break; } ALenum format = AL_FORMAT_MONO16; switch(pcmS16->inherit_super.channel_num) { case 1: // monoral format = AL_FORMAT_MONO16; break; case 2: // stereo format = AL_FORMAT_STEREO16; break; default: ERR_PRINT("only support monoral or stereo."); player_->inherit_super.error = ttLibC_updateError(Target_On_Util, Error_InvalidOperation); return false; } int num; ALuint buffer = 0; alGetSourcei(player_->source, AL_BUFFERS_PROCESSED, &num); if(num != -1 && num != 0) { alSourceUnqueueBuffers(player_->source, 1, &buffer); ALint frequency, channel, size, bits; alGetBufferi(buffer, AL_FREQUENCY, &frequency); alGetBufferi(buffer, AL_CHANNELS, &channel); alGetBufferi(buffer, AL_SIZE, &size); alGetBufferi(buffer, AL_BITS, &bits); double val = 1.0 * size / (bits / 8) / frequency / channel; player_->pts += val; } else { // check the space. int empty_num = -1; for(int i = 0;i < player_->total_buffer_num;++ i) { if(player_->buffers[i] == 0) { empty_num = i; break; } } if(empty_num == -1) { return false; } alGenBuffers(1, &buffer); player_->buffers[empty_num] = buffer; } alBufferData(buffer, format, pcmS16->l_data, pcmS16->l_stride, pcmS16->inherit_super.sample_rate); alSourceQueueBuffers(player_->source, 1, &buffer); int state; alGetSourcei(player_->source, AL_SOURCE_STATE, &state); if(state != AL_PLAYING) { // try to start play. alSourcePlay(player_->source); } return true; }
StreamSoundSource::StreamSoundSource() : file(0), fade_state(NoFading), looping(false) { alGenBuffers(STREAMFRAGMENTS, buffers); SoundManager::check_al_error("Couldn't allocate audio buffers: "); }
void Cyanide::audio_thread() { return; const char *device_list, *output_device = NULL; //void *audio_device = NULL; bool call[MAX_CALLS] = {0}, preview = 0; bool audio_filtering_enabled; // bool groups_audio[MAX_NUM_GROUPS] = {0}; int perframe = (av_DefaultSettings.audio_frame_duration * av_DefaultSettings.audio_sample_rate) / 1000; uint8_t buf[perframe * 2 * av_DefaultSettings.audio_channels], dest[perframe * 2 * av_DefaultSettings.audio_channels]; memset(buf, 0, sizeof(buf)); uint8_t audio_count = 0; bool record_on = 0; #ifdef AUDIO_FILTERING qDebug() << "Audio Filtering enabled"; #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES qDebug() << "Echo cancellation enabled"; #endif #endif qDebug() << "frame size:" << perframe; device_list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); if(device_list) { output_device = device_list; qDebug() << "Output Device List:"; while(*device_list) { qDebug() << device_list; //postmessage(NEW_AUDIO_OUT_DEVICE, 0, 0, (void*)device_list); device_list += strlen(device_list) + 1; } } device_out = alcOpenDevice(output_device); if(!device_out) { qDebug() << "alcOpenDevice() failed"; return; } int attrlist[] = { ALC_FREQUENCY, av_DefaultSettings.audio_sample_rate, ALC_INVALID }; context = alcCreateContext(device_out, attrlist); if(!alcMakeContextCurrent(context)) { qDebug() << "alcMakeContextCurrent() failed"; alcCloseDevice(device_out); return; } alGenSources(countof(source), source); static ALuint ringSrc[MAX_CALLS]; alGenSources(MAX_CALLS, ringSrc); /* Create buffer to store samples */ ALuint RingBuffer; alGenBuffers(1, &RingBuffer); { float frequency1 = 441.f; float frequency2 = 882.f; int seconds = 4; unsigned sample_rate = 22050; size_t buf_size = seconds * sample_rate * 2; //16 bit (2 bytes per sample) int16_t *samples = (int16_t*)malloc(buf_size * sizeof(int16_t)); if (!samples) return; /*Generate an electronic ringer sound that quickly alternates between two frequencies*/ int index = 0; for(index = 0; index < buf_size; ++index) { if ((index / (sample_rate)) % 4 < 2 ) {//4 second ring cycle, first 2 secondsring, the rest(2 seconds) is silence if((index / 1000) % 2 == 1) { samples[index] = 5000 * sin((2.0 * 3.1415926 * frequency1) / sample_rate * index); //5000=amplitude(volume level). It can be from zero to 32700 } else { samples[index] = 5000 * sin((2.0 * 3.1415926 * frequency2) / sample_rate * index); } } else { samples[index] = 0; } } alBufferData(RingBuffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate); free(samples); } { unsigned int i; for (i = 0; i < MAX_CALLS; ++i) { alSourcei(ringSrc[i], AL_LOOPING, AL_TRUE); alSourcei(ringSrc[i], AL_BUFFER, RingBuffer); } } #ifdef AUDIO_FILTERING Filter_Audio *f_a = NULL; #endif while(loop == LOOP_RUN || loop == LOOP_SUSPEND) { #ifdef AUDIO_FILTERING if (!f_a && audio_filtering_enabled) { f_a = new_filter_audio(av_DefaultSettings.audio_sample_rate); if (!f_a) { audio_filtering_enabled = 0; qDebug() << "filter audio failed"; } else { qDebug() << "filter audio on"; } } else if (f_a && !audio_filtering_enabled) { kill_filter_audio(f_a); f_a = NULL; qDebug() << "filter audio off"; } #else if (audio_filtering_enabled) audio_filtering_enabled = 0; #endif bool sleep = 1; if(record_on) { ALint samples; alcGetIntegerv(device_in, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { alcCaptureSamples(device_in, buf, perframe); if (samples >= perframe * 2) { sleep = 0; } } } #ifdef AUDIO_FILTERING #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES if (f_a && audio_filtering_enabled) { ALint samples; alcGetIntegerv(device_out, ALC_LOOPBACK_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { int16_t buffer[perframe]; alcCaptureSamplesLoopback(device_out, buffer, perframe); pass_audio_output(f_a, buffer, perframe); set_echo_delay_ms(f_a, 5); if (samples >= perframe * 2) { sleep = 0; } } } #endif #endif #ifdef AUDIO_FILTERING if (f_a && filter_audio(f_a, (int16_t*)buf, perframe) == -1) { qDebug() << "filter audio error"; } #endif if(preview) { audio_play(0, (int16_t*)buf, perframe, av_DefaultSettings.audio_channels, av_DefaultSettings.audio_sample_rate); } int i; for(i = 0; i < MAX_CALLS; i++) { if(call[i]) { int r; if((r = toxav_prepare_audio_frame(toxav, i, dest, sizeof(dest), (const int16_t*)buf, perframe)) < 0) { qDebug() << "toxav_prepare_audio_frame error" << r; continue; } if((r = toxav_send_audio(toxav, i, dest, r)) < 0) { qDebug() << "toxav_send_audio error" << r; } } } if (sleep) { usleep(5000); } } #ifdef AUDIO_FILTERING kill_filter_audio(f_a); #endif //missing some cleanup ? alDeleteSources(MAX_CALLS, ringSrc); alDeleteSources(countof(source), source); alDeleteBuffers(1, &RingBuffer); if(device_in) { if(record_on) { alcCaptureStop(device_in); } alcCaptureCloseDevice(device_in); } alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device_out); }
static int init(struct ao *ao) { float position[3] = {0, 0, 0}; float direction[6] = {0, 0, -1, 0, 1, 0}; ALCdevice *dev = NULL; ALCcontext *ctx = NULL; ALCint freq = 0; ALCint attribs[] = {ALC_FREQUENCY, ao->samplerate, 0, 0}; int i; struct priv *p = ao->priv; if (ao_data) { MP_FATAL(ao, "Not reentrant!\n"); return -1; } ao_data = ao; struct mp_chmap_sel sel = {0}; for (i = 0; speaker_pos[i].id != -1; i++) mp_chmap_sel_add_speaker(&sel, speaker_pos[i].id); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto err_out; struct speaker speakers[MAX_CHANS]; for (i = 0; i < ao->channels.num; i++) { speakers[i].id = -1; for (int n = 0; speaker_pos[n].id >= 0; n++) { if (speaker_pos[n].id == ao->channels.speaker[i]) speakers[i] = speaker_pos[n]; } if (speakers[i].id < 0) { MP_FATAL(ao, "Unknown channel layout\n"); goto err_out; } } char *dev_name = ao->device; dev = alcOpenDevice(dev_name && dev_name[0] ? dev_name : NULL); if (!dev) { MP_FATAL(ao, "could not open device\n"); goto err_out; } ctx = alcCreateContext(dev, attribs); alcMakeContextCurrent(ctx); alListenerfv(AL_POSITION, position); alListenerfv(AL_ORIENTATION, direction); alGenSources(ao->channels.num, sources); for (i = 0; i < ao->channels.num; i++) { cur_buf[i] = 0; unqueue_buf[i] = 0; alGenBuffers(NUM_BUF, buffers[i]); alSourcefv(sources[i], AL_POSITION, speakers[i].pos); alSource3f(sources[i], AL_VELOCITY, 0, 0, 0); } alcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq); if (alcGetError(dev) == ALC_NO_ERROR && freq) ao->samplerate = freq; p->al_format = AL_FALSE; int try_formats[AF_FORMAT_COUNT]; af_get_best_sample_formats(ao->format, try_formats); for (int n = 0; try_formats[n]; n++) { p->al_format = get_al_format(try_formats[n]); if (p->al_format != AL_FALSE) { ao->format = try_formats[n]; break; } } if (p->al_format == AL_FALSE) { MP_FATAL(ao, "Can't find appropriate sample format.\n"); uninit(ao); goto err_out; } p->chunk_size = CHUNK_SAMPLES * af_fmt_to_bytes(ao->format); return 0; err_out: ao_data = NULL; return -1; }
//----------------------------------------------------------------------------// SoundBuffer::SoundBuffer(const Ogre::String& name): mDuration(0), mChannels(0), mFrequency(0), mSize(0), mBits(0) { mBuffers = new ALuint[1]; alGenBuffers(1, mBuffers); }
/* ======================== idSoundVoice_OpenAL::Create ======================== */ void idSoundVoice_OpenAL::Create( const idSoundSample* leadinSample_, const idSoundSample* loopingSample_ ) { if( IsPlaying() ) { // This should never hit Stop(); return; } triggered = true; leadinSample = ( idSoundSample_OpenAL* )leadinSample_; loopingSample = ( idSoundSample_OpenAL* )loopingSample_; if( alIsSource( openalSource ) && CompatibleFormat( leadinSample ) ) { sampleRate = leadinSample->format.basic.samplesPerSec; } else { DestroyInternal(); formatTag = leadinSample->format.basic.formatTag; numChannels = leadinSample->format.basic.numChannels; sampleRate = leadinSample->format.basic.samplesPerSec; //soundSystemLocal.hardware.pXAudio2->CreateSourceVoice( &pSourceVoice, ( const WAVEFORMATEX* )&leadinSample->format, XAUDIO2_VOICE_USEFILTER, 4.0f, &streamContext ); CheckALErrors(); alGenSources( 1, &openalSource ); if( CheckALErrors() != AL_NO_ERROR ) //if( pSourceVoice == NULL ) { // If this hits, then we are most likely passing an invalid sample format, which should have been caught by the loader (and the sample defaulted) return; } alSourcef( openalSource, AL_ROLLOFF_FACTOR, 0.0f ); //if( ( loopingSample == NULL && leadinSample->openalBuffer != 0 ) || ( loopingSample != NULL && soundShader->entries[0]->hardwareBuffer ) ) if( leadinSample->openalBuffer != 0 ) { alSourcei( openalSource, AL_BUFFER, 0 ); // handle uncompressed (non streaming) single shot and looping sounds /* if( triggered ) { alSourcei( openalSource, AL_BUFFER, looping ? chan->soundShader->entries[0]->openalBuffer : leadinSample->openalBuffer ); } */ } else { //if( triggered ) // handle streaming sounds (decode on the fly) both single shot AND looping alSourcei( openalSource, AL_BUFFER, 0 ); alDeleteBuffers( 3, &lastopenalStreamingBuffer[0] ); lastopenalStreamingBuffer[0] = openalStreamingBuffer[0]; lastopenalStreamingBuffer[1] = openalStreamingBuffer[1]; lastopenalStreamingBuffer[2] = openalStreamingBuffer[2]; alGenBuffers( 3, &openalStreamingBuffer[0] ); /* if( soundSystemLocal.alEAXSetBufferMode ) { soundSystemLocal.alEAXSetBufferMode( 3, &chan->openalStreamingBuffer[0], alGetEnumValue( ID_ALCHAR "AL_STORAGE_ACCESSIBLE" ) ); } */ openalStreamingBuffer[0]; openalStreamingBuffer[1]; openalStreamingBuffer[2]; } if( s_debugHardware.GetBool() ) { if( loopingSample == NULL || loopingSample == leadinSample ) { idLib::Printf( "%dms: %i created for %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>" ); } else { idLib::Printf( "%dms: %i created for %s and %s\n", Sys_Milliseconds(), openalSource, leadinSample ? leadinSample->GetName() : "<null>", loopingSample ? loopingSample->GetName() : "<null>" ); } } } sourceVoiceRate = sampleRate; //pSourceVoice->SetSourceSampleRate( sampleRate ); //pSourceVoice->SetVolume( 0.0f ); alSourcei( openalSource, AL_SOURCE_RELATIVE, AL_TRUE ); alSource3f( openalSource, AL_POSITION, 0.0f, 0.0f, 0.0f ); // RB: FIXME 0.0f ? alSourcef( openalSource, AL_GAIN, 1.0f ); //OnBufferStart( leadinSample, 0 ); }
/* ============== S_EndLoadSound ============== */ qboolean S_EndLoadSound( sfx_t *sfx ) { wavinfo_t info; byte* data; ALuint Buffer; assert(sfx->iFlags & SFX_FLAG_LOADING); sfx->iFlags &= ~SFX_FLAG_LOADING; // was the read successful? if (Sys_StreamIsError(sfx->iStreamHandle)) { #if defined(FINAL_BUILD) /* extern void ERR_DiscFail(bool); ERR_DiscFail(false); */ #endif Sys_StreamClose(sfx->iStreamHandle); Z_Free(sfx->pSoundData); sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT; return qfalse; } Sys_StreamClose(sfx->iStreamHandle); SND_TouchSFX(sfx); sfx->iLastTimeUsed = Com_Milliseconds()+1; // why +1? Hmmm, leave it for now I guess // loading a WAV, presumably... data = (byte*)sfx->pSoundData; info = GetWavInfo( data ); if (info.size == 0) { Z_Free(sfx->pSoundData); sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT; return qfalse; } sfx->iSoundLength = info.size; // make sure we have enough space for the sound SND_update(sfx); // Clear Open AL Error State alGetError(); // Generate AL Buffer alGenBuffers(1, &Buffer); // Copy audio data to AL Buffer alBufferData(Buffer, info.format, data, sfx->iSoundLength, info.rate); if (alGetError() != AL_NO_ERROR) { Z_Free(sfx->pSoundData); sfx->iFlags |= SFX_FLAG_UNLOADED; return qfalse; } sfx->Buffer = Buffer; #ifdef _GAMECUBE Z_Free(sfx->pSoundData); #endif sfx->iFlags |= SFX_FLAG_RESIDENT; return qtrue; }
void Music::MusicThread() { // Allocation of streaming buffers ALuint buffers[NAZARA_AUDIO_STREAMED_BUFFER_COUNT]; alGenBuffers(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, buffers); for (unsigned int buffer : buffers) { if (FillAndQueueBuffer(buffer)) break; // We have reached the end of the stream, there is no use to add new buffers } alSourcePlay(m_source); // Reading loop (Filling new buffers as playing) while (m_impl->streaming) { // The reading has stopped, we have reached the end of the stream SoundStatus status = GetInternalStatus(); if (status == SoundStatus_Stopped) { m_impl->streaming = false; break; } Nz::LockGuard lock(m_impl->bufferLock); // We treat read buffers ALint processedCount = 0; alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processedCount); while (processedCount--) { ALuint buffer; alSourceUnqueueBuffers(m_source, 1, &buffer); ALint bits, size; alGetBufferi(buffer, AL_BITS, &bits); alGetBufferi(buffer, AL_SIZE, &size); if (bits != 0) m_impl->processedSamples += (8 * size) / bits; if (FillAndQueueBuffer(buffer)) break; } lock.Unlock(); // We go back to sleep Thread::Sleep(50); } // Stop playing of the sound (in the case where it has not been already done) alSourceStop(m_source); // We delete buffers from the stream ALint queuedBufferCount; alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queuedBufferCount); ALuint buffer; for (ALint i = 0; i < queuedBufferCount; ++i) alSourceUnqueueBuffers(m_source, 1, &buffer); alDeleteBuffers(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, buffers); }
AudioBuffer::AudioBuffer(const String &filename) { if (filename.ExtractExt() == "wav") { m_alBuffer = 0; File * file = new File(filename, FILE_READ); int32 chunkId = file->ReadInt(); int32 riffChunkSize = file->ReadInt(); int32 format = file->ReadInt(); int32 subChunkId = file->ReadInt(); int32 fmtChunkSize = file->ReadInt(); int16 audioFormat = file->ReadInt16(); int16 channels = file->ReadInt16(); int32 sampleRate = file->ReadInt(); int32 byteRate = file->ReadInt(); int16 blockAlign = file->ReadInt16(); int16 bitsPerSample = file->ReadInt16(); if (fmtChunkSize > 16) { int16 extraParamsSize = file->ReadInt16(); file->Seek(file->Pos() + extraParamsSize); } char text[5] = ""; file->ReadBytes(text, 4); while (String(text) != "data" && !file->Eof()) { file->ReadBytes(text, 4); if (String(text) == "data") break; file->Seek(file->Pos() + 4); } int32 dataSize = file->ReadInt(); uint32 * data = (uint32 *)malloc(dataSize); file->ReadBytes(data, dataSize); ALenum bufferFormat; if (bitsPerSample == 8) { if (channels == 1) bufferFormat = AL_FORMAT_MONO8; else bufferFormat = AL_FORMAT_STEREO8; } else { if (channels == 1) bufferFormat = AL_FORMAT_MONO16; else bufferFormat = AL_FORMAT_STEREO16; } alGenBuffers(1, &m_alBuffer); alBufferData(m_alBuffer, bufferFormat, data, dataSize, sampleRate); delete file; free(data); } else if (filename.ExtractExt() == "ogg") { stb_vorbis * file = stb_vorbis_open_filename(filename.ToCString(), nullptr, nullptr); if (file) { stb_vorbis_info info = stb_vorbis_get_info(file); uint32 size = stb_vorbis_stream_length_in_samples(file) * info.channels; int16 * buffer = (int16 *)malloc(size * sizeof(int16)); stb_vorbis_get_samples_short_interleaved(file, info.channels, buffer, size); alGenBuffers(1, &m_alBuffer); ALenum bufferFormat; if (info.channels == 1) bufferFormat = AL_FORMAT_MONO16; else bufferFormat = AL_FORMAT_STEREO16; alBufferData(m_alBuffer, bufferFormat, buffer, size, info.sample_rate); stb_vorbis_close(file); free(buffer); } } }
/** Plays the audio data from the given file * \param fileHandle,volume,onFinished,user_data see sound_PlayStream() * \param streamBufferSize the size to use for the decoded audio buffers * \param buffer_count the amount of audio buffers to use * \see sound_PlayStream() for details about the rest of the function * parameters and other details. */ AUDIO_STREAM* sound_PlayStreamWithBuf(PHYSFS_file* fileHandle, float volume, void (*onFinished)(void*), void* user_data, size_t streamBufferSize, unsigned int buffer_count) { #if !defined(WZ_NOSOUND) AUDIO_STREAM* stream; ALuint* buffers = alloca(sizeof(ALuint) * buffer_count); ALint error; unsigned int i; if ( !openal_initialized ) { debug(LOG_WARNING, "OpenAL isn't initialized, not creating an audio stream"); return NULL; } stream = malloc(sizeof(AUDIO_STREAM)); if (stream == NULL) { debug(LOG_FATAL, "sound_PlayStream: Out of memory"); abort(); return NULL; } // Clear error codes alGetError(); // Retrieve an OpenAL sound source alGenSources(1, &(stream->source)); error = sound_GetError(); if (error != AL_NO_ERROR) { // Failed to create OpenAL sound source, so bail out... debug(LOG_SOUND, "alGenSources failed, most likely out of sound sources"); free(stream); return NULL; } stream->fileHandle = fileHandle; stream->decoder = sound_CreateOggVorbisDecoder(stream->fileHandle, false); if (stream->decoder == NULL) { debug(LOG_ERROR, "sound_PlayStream: Failed to open audio file for decoding"); free(stream); return NULL; } stream->volume = volume; stream->bufferSize = streamBufferSize; alSourcef(stream->source, AL_GAIN, stream->volume); // HACK: this is a workaround for a bug in the 64bit implementation of OpenAL on GNU/Linux // The AL_PITCH value really should be 1.0. alSourcef(stream->source, AL_PITCH, 1.001f); // Create some OpenAL buffers to store the decoded data in alGenBuffers(buffer_count, buffers); sound_GetError(); // Fill some buffers with audio data for (i = 0; i < buffer_count; ++i) { // Decode some audio data soundDataBuffer* soundBuffer = sound_DecodeOggVorbis(stream->decoder, stream->bufferSize); // If we actually decoded some data if (soundBuffer && soundBuffer->size > 0) { // Determine PCM data format ALenum format = (soundBuffer->channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; // Copy the audio data into one of OpenAL's own buffers alBufferData(buffers[i], format, soundBuffer->data, soundBuffer->size, soundBuffer->frequency); sound_GetError(); // Clean up our memory free(soundBuffer); } else { // If no data has been decoded we're probably at the end of our // stream. So cleanup the excess stuff here. // First remove the data buffer itself free(soundBuffer); // Then remove OpenAL's buffers alDeleteBuffers(buffer_count - i, &buffers[i]); sound_GetError(); break; } } // Bail out if we didn't fill any buffers if (i == 0) { debug(LOG_ERROR, "Failed to fill buffers with decoded audio data!"); // Destroy the decoder sound_DestroyOggVorbisDecoder(stream->decoder); // Destroy the OpenAL source alDeleteSources(1, &stream->source); // Free allocated memory free(stream); return NULL; } // Attach the OpenAL buffers to our OpenAL source // (i = the amount of buffers we worked on in the above for-loop) alSourceQueueBuffers(stream->source, i, buffers); sound_GetError(); // Start playing the source alSourcePlay(stream->source); sound_GetError(); // Set callback info stream->onFinished = onFinished; stream->user_data = user_data; // Prepend this stream to the linked list stream->next = active_streams; active_streams = stream; return stream; #else return NULL; #endif }
bool OpenALAudio::StreamContext::stream_data(int new_buffer_count) { const size_t BUFFER_SIZE = 0x4000; /* * This constant determines how many milliseconds of audio data go into * one buffer. The larger it is, the less probability of skipping, but * the longer the delay from calling stop() to the point when it * actually stops. */ const size_t MAX_BUFFER_TIME_MS = 50; uint8_t data[BUFFER_SIZE]; size_t frames_read; size_t max_frames; ALenum format; ALuint buf; ALint state; if (!this->streaming) return false; format = openal_format(this->stream); max_frames = this->stream->frame_rate() * MAX_BUFFER_TIME_MS / 1000; for (;;) { buf = 0; if (new_buffer_count > 0) { alGenBuffers(1, &buf); if (!check_al()) goto err; new_buffer_count--; } else { ALint processed; alGetSourcei(this->source, AL_BUFFERS_PROCESSED, &processed); if (processed == 0) break; alSourceUnqueueBuffers(this->source, 1, &buf); if (!check_al()) goto err; } size_t space_frames = sizeof(data) / this->stream->frame_size(); space_frames = MIN(space_frames, max_frames); frames_read = this->stream->read(data, space_frames); if (frames_read == 0) { if (this->looping) { this->stream->seek(this->loop_start_frame); frames_read = this->stream->read(data, space_frames); if (frames_read == 0) { this->streaming = false; break; } } else { this->streaming = false; break; } } if (this->fade_frames != 0) this->apply_fading(data, frames_read); alBufferData(buf, format, data, frames_read * this->stream->frame_size(), this->stream->frame_rate()); if (!check_al()) goto err; alSourceQueueBuffers(this->source, 1, &buf); if (!check_al()) goto err; } if (!this->streaming) { alDeleteBuffers(1, &buf); check_al(); } alGetSourcei(this->source, AL_SOURCE_STATE, &state); if (state != AL_PLAYING) { alSourcePlay(this->source); check_al(); } return this->streaming; err: if (buf != 0) alDeleteBuffers(1, &buf); this->streaming = false; return false; }
int main(int argc, char* argv[]) { /* initialize OpenAL */ init_al(); srand(time(NULL)); /* Create buffer to store samples */ ALuint buf; alGenBuffers(1, &buf); al_check_error(); /* Fill buffer with Sine-Wave */ float freq = 400.f; int seconds = 4; unsigned sample_rate = 8000; size_t buf_size = seconds * sample_rate; //os vetores de frequencia e amplitude serão recebidos //a partir da imagem de profundidade //o tamanho de frequencias eh igual ao numero de pixels int freq_size = 256; float *frequencias; frequencias = new float[freq_size]; float freq_aux; for(int i=0; i<256; ++i) { if (i == 0) frequencias[i] = 100; else frequencias[i] = frequencias[i-1] + 15; } //o tamanho de amplitudes eh igual ao numero de pixels int amp_size = 256; //igual ao de frequencias float *amplitudes; amplitudes = new float[amp_size]; for(int i=0; i<256; ++i) { amplitudes[i] = float(rand()%4) / 2; //amplitudes[i] = 1; } short *samples; samples = new short[buf_size]; for(int i=0; i<buf_size; ++i) { //samples[i] = 32760 * sin( (2.f*float(M_PI)*freq)/sample_rate * i ); samples[i] = 0; for (int j=0; j<freq_size; ++j){ samples[i] = samples[i] + 32760 * amplitudes[j] * sin( (2.f*float(M_PI)*frequencias[j])/sample_rate * i ); } //samples[i] = 32760 * sin( (2.f*float(M_PI)*float(rand()%300+100))/sample_rate * i ); } /* Download buffer to OpenAL */ alBufferData(buf, AL_FORMAT_MONO16, samples, buf_size, sample_rate); al_check_error(); /* Set-up sound source and play buffer */ ALuint src = 0; alGenSources(1, &src); alSourcei(src, AL_BUFFER, buf); alSourcePlay(src); std::cout << "dasdasdas"; /* While sound is playing, sleep */ al_check_error(); //sleep(seconds); for(int i = 0; i< 1000000000; i++); /* Dealloc OpenAL */ exit_al(); al_check_error(); return 0; }
/*! Initializes the sound device * * @returns ICRESULT Success/failure of initializing the device **/ ICRESULT icSoundDeviceAL::Initialize(void) { ICRESULT res = Cleanup(); if(ICEFAIL(res)) { ALenum err = alGetError(); icWarningf("icSoundDeviceAL::Initialize failed with error: %i", err); return res; } m_Device = alcOpenDevice(NULL); if (NULL == m_Device) { ALenum err = alGetError(); icWarningf("icSoundDeviceAL::Initialize failed with error: %i", err); return IC_FAIL_GEN; } m_Context = alcCreateContext(m_Device,NULL); if (!alcMakeContextCurrent(m_Context)) { ALenum err = alGetError(); icWarningf("icSoundDeviceAL::Initialize failed with error: %i", err); return IC_FAIL_GEN; } ALenum err = alGetError(); if (err) { ALenum err = alGetError(); icWarningf("icSoundDeviceAL::Initialize failed with error: %i", err); return IC_FAIL_GEN; } ALuint temp_sounds[ICSND_MAX_PLAYING]; ALuint temp_buffers[ICSND_MAX_SOURCE]; memset(temp_sounds,0,sizeof(ALuint)*ICSND_MAX_PLAYING); memset(temp_buffers,0,sizeof(ALuint)*ICSND_MAX_SOURCE); // create the sources alGenSources(ICSND_MAX_PLAYING, temp_sounds); err = alGetError(); if (err) { ALenum err = alGetError(); icWarningf("icSoundDeviceAL::Initialize failed with error: %i", err); return IC_FAIL_GEN; } // create the buffers alGenBuffers(ICSND_MAX_SOURCE, temp_buffers); err = alGetError(); if (err) { ALenum err = alGetError(); icWarningf("icSoundDeviceAL::Initialize failed with error: %i", err); return IC_FAIL_GEN; } for (int i=0; i<ICSND_MAX_SOURCE; ++i) m_SrcBufs[i].buffID = temp_buffers[i]; for (int i=0; i<ICSND_MAX_PLAYING; ++i) { m_Sounds[i] = new icSoundAL(); m_NumFreeSounds++; icSoundAL* temp = (icSoundAL*)m_Sounds[i]; temp->m_ALsource = temp_sounds[i]; temp->m_bInitialized = true; } icMinHeapBuild(m_Sounds,m_NumFreeSounds); // TODO 3d stuff //alDopplerFactor(ALfloat factor); //alDopplerVelocity(ALfloat velocity); return IC_OK; }// END FUNCTION Initialize(void)
static int SmpLoad(V3XA_HANDLE *sam) { alGenBuffers(1, (ALuint *)&sam->sampleID); alBufferData((ALuint)sam->sampleID, (sam->sampleFormat & V3XA_FMTSTEREO) ? ((sam->sampleFormat & V3XA_FMT16BIT) ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8) : ((sam->sampleFormat & V3XA_FMT16BIT) ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8), sam->sample, sam->length, sam->samplingRate); return 0; }
Sound::Sound (ALenum format, ALsizei frequency, const Buffer * samples) : _format(format), _frequency(frequency) { alGenBuffers(1, &_buffer_id); alBufferData(_buffer_id, _format, samples->begin(), samples->size(), _frequency); }
//----------------------------------------------------------------------------- bool MusicOggStream::load(const std::string& filename) { if (isPlaying()) stopMusic(); m_error = true; m_fileName = filename; if(m_fileName=="") return false; m_oggFile = fopen(m_fileName.c_str(), "rb"); if(!m_oggFile) { Log::error("MusicOgg", "Loading Music: %s failed (fopen returned NULL)\n", m_fileName.c_str()); return false; } #if defined( WIN32 ) || defined( WIN64 ) const int result = ov_open_callbacks((void *)m_oggFile, &m_oggStream, NULL, 0, OV_CALLBACKS_DEFAULT); #else const int result = ov_open(m_oggFile, &m_oggStream, NULL, 0); #endif if (result < 0) { fclose(m_oggFile); const char* errorMessage; switch (result) { case OV_EREAD: errorMessage = "OV_EREAD"; break; case OV_ENOTVORBIS: errorMessage = "OV_ENOTVORBIS"; break; case OV_EVERSION: errorMessage = "OV_EVERSION"; break; case OV_EBADHEADER: errorMessage = "OV_EBADHEADER"; break; case OV_EFAULT: errorMessage = "OV_EFAULT"; break; default: errorMessage = "Unknown Error"; } Log::error("MusicOgg", "Loading Music: %s failed : ov_open returned error code %i (%s)\n", m_fileName.c_str(), result, errorMessage); return false; } m_vorbisInfo = ov_info(&m_oggStream, -1); if (m_vorbisInfo->channels == 1) nb_channels = AL_FORMAT_MONO16; else nb_channels = AL_FORMAT_STEREO16; alGenBuffers(2, m_soundBuffers); if (check("alGenBuffers") == false) return false; alGenSources(1, &m_soundSource); if (check("alGenSources") == false) return false; alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0); alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, 0.0 ); alSourcef (m_soundSource, AL_GAIN, 1.0 ); alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE ); m_error=false; return true; } // load
int main() { char input[INPUT_BUFFER]; char *words[MAX_WORDS]; int count_of_words, signal_index, sleep_usec, count_of_processed, count_of_queued; int i; ALint state; ALshort signals[BUFFER]; ALCdevice *device; ALCcontext *context; ALuint buffer, source; sleep_usec = (int)(((1.0 / SAMPLING_FREQUENCY) * MAX_WORDS / 2 ) * 1000 * 1000); device = alcOpenDevice(NULL); context = alcCreateContext(device, NULL); alcMakeContextCurrent(context); alGenSources(1, &source); alSourcei(source, AL_SOURCE_TYPE, AL_STREAMING); while (fgets(input, INPUT_BUFFER, stdin) != NULL) { puts("### got input"); count_of_words = split_string(input, words); signal_index = 0; for (i = 0; i < count_of_words; i++) { signals[signal_index++] = (ALshort)atoi(words[i]); } if (alGetSourcei(source, AL_BUFFERS_QUEUED, &count_of_queued), count_of_queued < COUNT_OF_BUFFERS) { alGenBuffers(1, &buffer); } else { while (alGetSourcei(source, AL_BUFFERS_PROCESSED, &count_of_processed), count_of_processed == 0) { usleep(sleep_usec); } for (i = 0; i < count_of_processed; i++) { alSourceUnqueueBuffers(source, 1, &buffer); } } alBufferData(buffer, AL_FORMAT_MONO16, signals, sizeof(ALshort) * signal_index, SAMPLING_FREQUENCY); alSourceQueueBuffers(source, 1, &buffer); if (alGetSourcei(source, AL_SOURCE_STATE, &state), state != AL_PLAYING) { puts("--- start playing"); alGetSourcei(source, AL_BUFFERS_PROCESSED, &count_of_processed); for (i = 0; i < count_of_processed - 1; i++) { printf("--- unqueue: %d\n", i); alSourceUnqueueBuffers(source, 1, &buffer); } alSourcePlay(source); } } alSourceStop(source); alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); return 0; }
void Sound::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) { if (!GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled())) return; std::string filename = path.string(); ALuint current_buffer; ALenum source_state; ALsizei ogg_freq; FILE *file = 0; int m_i; bool found_buffer = true; bool found_source = false; #ifdef FREEORION_WIN32 ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; #endif if (alcGetCurrentContext() != 0) { /* First check if the sound data of the file we want to play is already buffered somewhere */ std::map<std::string, ALuint>::iterator it = m_buffers.find(filename); if (it != m_buffers.end()) current_buffer = it->second; else { if ((file = fopen(filename.c_str(), "rb")) != 0) // make sure we CAN open it { OggVorbis_File ogg_file; vorbis_info *vorbis_info; ALenum ogg_format; #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(file, &ogg_file, 0, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(file, &ogg_file, 0, 0))) // check if it's a proper ogg #endif { ov_test_open(&ogg_file); // it is, now fully open the file /* now we need to take some info we will need later */ vorbis_info = ov_info(&ogg_file, -1); if (vorbis_info->channels == 1) ogg_format = AL_FORMAT_MONO16; else ogg_format = AL_FORMAT_STEREO16; ogg_freq = vorbis_info->rate; ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2; if (byte_size <= 1024 * 1024 * 1024) { /* fill up the buffers and queue them up for the first time */ ALuint sound_handle; alGenBuffers(1, &sound_handle); int loop = 0; RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop); current_buffer = sound_handle; m_buffers.insert(std::make_pair(filename, sound_handle)); } else { Logger().errorStream() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n"; } ov_clear(&ogg_file); } else { Logger().errorStream() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n"; } } } if (found_buffer) { /* Now that we have the buffer, we need to find a source to send it to */ for (m_i = 1; m_i < NUM_SOURCES; ++m_i) { // as we're playing sounds we start at 1. 0 is reserved for music alGetSourcei(m_sources[m_i],AL_SOURCE_STATE,&source_state); if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) { found_source = true; alSourcei(m_sources[m_i], AL_BUFFER, current_buffer); alSourcePlay(m_sources[m_i]); break; // so that the sound won't block all the sources } } if (!found_source) Logger().errorStream() << "PlaySound: Could not find aviable source - playback aborted\n"; } source_state = alGetError(); if (source_state != AL_NONE) Logger().errorStream() << "PlaySound: OpenAL ERROR: " << alGetString(source_state); /* it's important to check for errors, as some functions won't work properly if * they're called when there is a unchecked previous error. */ } }
int main(void) { /*Отсюда нужно две функции - 1) получение в виде массива (строки) данных с микрофона за время необработки 2)Проигрвание строки равной значению */ const ALCchar * devices; const ALCchar * ptr; ALCdevice * mainDev; ALCcontext * mainContext; ALCdevice * captureDev; ALubyte captureBuffer[1048576]; ALubyte *captureBufPtr; ALint samplesAvailable; ALint samplesCaptured; time_t currentTime; time_t lastTime; ALuint buffer; ALuint source; ALint playState; int i; // Print the list of capture devices printf("Available playback devices:\n"); devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER); ptr = devices; //while (ptr[0] != NULL) while (*ptr) { printf(" %s\n", ptr); ptr += strlen(ptr) + 1; } // Open a playback device and create a context first printf("Opening playback device:\n"); mainDev = alcOpenDevice(NULL); if (mainDev == NULL) { printf("Unable to open playback device!\n"); exit(1); } devices = alcGetString(mainDev, ALC_DEVICE_SPECIFIER); printf(" opened device '%s'\n", devices); mainContext = alcCreateContext(mainDev, NULL); if (mainContext == NULL) { printf("Unable to create playback context!\n"); exit(1); } printf(" created playback context\n"); // Make the playback context current alcMakeContextCurrent(mainContext); alcProcessContext(mainContext); // Print the list of capture devices printf("Available capture devices:\n"); devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); ptr = devices; //while (ptr[0] != NULL) while (*ptr) { printf(" %s\n", ptr); ptr += strlen(ptr) + 1; } // Open the default device printf("Opening capture device:\n"); captureDev = alcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 800); if (captureDev == NULL) { printf(" Unable to open device!\n"); exit(1); } devices = alcGetString(captureDev, ALC_CAPTURE_DEVICE_SPECIFIER); printf(" opened device %s\n", devices); // Wait for three seconds to prompt the user for (i = 3; i > 0; i--) { printf("Starting capture in %d...\r", i); fflush(stdout); lastTime = time(NULL); currentTime = lastTime; while (currentTime == lastTime) { currentTime = time(NULL); usleep(100000); } } printf("Starting capture NOW!\n"); fflush(stdout); lastTime = currentTime; // Capture (roughly) five seconds of audio alcCaptureStart(captureDev); samplesCaptured = 0; captureBufPtr = captureBuffer; while (currentTime < (lastTime + 5)) { // Get the number of samples available alcGetIntegerv(captureDev, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable); // Copy the samples to our capture buffer if (samplesAvailable > 0) { alcCaptureSamples(captureDev, captureBufPtr, samplesAvailable); samplesCaptured += samplesAvailable; printf("Captured %d samples (adding %d)\r", samplesCaptured, samplesAvailable); fflush(stdout); // Advance the buffer (two bytes per sample * number of samples) captureBufPtr += samplesAvailable * 2; } // Wait for a bit usleep(10000); // Update the clock currentTime = time(NULL); } printf("\nPausing capture.\n"); alcCaptureStop(captureDev); // Wait for three seconds to prompt the user for (i = 3; i > 0; i--) { printf("Resuming capture in %d...\r", i); fflush(stdout); lastTime = time(NULL); currentTime = lastTime; while (currentTime == lastTime) { currentTime = time(NULL); usleep(100000); } } printf("Resuming capture NOW!\n"); fflush(stdout); lastTime = currentTime; // Capture (roughly) five seconds of audio alcCaptureStart(captureDev); while (currentTime < (lastTime + 5)) { // Get the number of samples available alcGetIntegerv(captureDev, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable); // Copy the samples to our capture buffer if (samplesAvailable > 0) { alcCaptureSamples(captureDev, captureBufPtr, samplesAvailable); samplesCaptured += samplesAvailable; printf("Captured %d samples (adding %d)\r", samplesCaptured, samplesAvailable); fflush(stdout); // Advance the buffer (two bytes per sample * number of samples) captureBufPtr += samplesAvailable * 2; } // Wait for a bit usleep(10000); // Update the clock currentTime = time(NULL); } printf("\nDone capturing.\n"); alcCaptureStop(captureDev); // Play back the captured data printf("Starting playback...\n"); fflush(stdout); // Generate an OpenAL buffer for the captured data alGenBuffers(1, &buffer); alGenSources(1, &source); alBufferData(buffer, AL_FORMAT_MONO16, captureBuffer,samplesCaptured*2, 8000); alSourcei(source, AL_BUFFER, buffer); alSourcePlay(source); // Wait for the source to stop playing playState = AL_PLAYING; while (playState == AL_PLAYING) { printf(" source %d is playing...\r", source); fflush(stdout); alGetSourcei(source, AL_SOURCE_STATE, &playState); usleep(100000); } printf("\nDone with playback.\n"); fflush(stdout); // Shut down OpenAL alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); alcMakeContextCurrent(NULL); alcCloseDevice(mainDev); alcCaptureCloseDevice(captureDev); }
/* * queue pcm data. * @param device openalDevice object. * @param pcms16 pcms16 object. */ bool ttLibC_AlDevice_queue(ttLibC_AlDevice *device, ttLibC_PcmS16 *pcms16) { if(device == NULL) { return false; } if(pcms16 == NULL) { return false; } switch(pcms16->type) { case PcmS16Type_bigEndian: case PcmS16Type_bigEndian_planar: ERR_PRINT("big endian is not support by openal."); return false; case PcmS16Type_littleEndian: break; case PcmS16Type_littleEndian_planar: if(pcms16->inherit_super.channel_num != 1) { ERR_PRINT("planar data is supported only monoral."); return false; } break; default: ERR_PRINT("unknown pcms16Type.%d", pcms16->type); return false; } ttLibC_AlDevice_ *device_ = (ttLibC_AlDevice_ *)device; ALenum format = AL_FORMAT_MONO16; switch(pcms16->inherit_super.channel_num) { case 1: // monoral format = AL_FORMAT_MONO16; break; case 2: // stereo format = AL_FORMAT_STEREO16; break; default: ERR_PRINT("only monoral or stereo for openal."); return false; } int num; ALuint buffer = 0; alGetSourcei(device_->source, AL_BUFFERS_PROCESSED, &num); if(num != -1 && num != 0) { // reuse played buffer. alSourceUnqueueBuffers(device_->source, 1, &buffer); } else { // establish new buffer. alGetSourcei(device_->source, AL_BUFFERS_QUEUED, &num); if(num == device_->inherit_super.buffer_num) { ERR_PRINT("buffer is already fulled. cannot queue anymore."); return false; } } if(buffer == 0) { alGenBuffers(1, &buffer); for(uint32_t i = 0;i < device_->inherit_super.buffer_num;++ i) { if(device_->buffers[i] == 0) { device_->buffers[i] = buffer; break; } } } alBufferData(buffer, format, pcms16->l_data, pcms16->l_stride, pcms16->inherit_super.sample_rate); alSourceQueueBuffers(device_->source, 1, &buffer); return true; }
void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) { LLVector3 wind_pos; F64 pitch; F64 center_freq; ALenum error; if (!mEnableWind) return; if(!mWindBuf) return; if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) { // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) // need to convert this to the conventional orientation DS3D and OpenAL use // where +X = right, +Y = up, +Z = backwards wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); pitch = 1.0 + mapWindVecToPitch(wind_vec); center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); mWindGen->mTargetFreq = (F32)center_freq; mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); alSourcei(mWindSource, AL_LOOPING, AL_FALSE); alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); } // ok lets make a wind buffer now int processed, queued, unprocessed; alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); unprocessed = queued - processed; // ensure that there are always at least 3x as many filled buffers // queued as we managed to empty since last time. mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed); mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0); //LL_INFOS("OpenAL") << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << LL_ENDL; while(processed--) // unqueue old buffers { ALuint buffer; int error; alGetError(); /* clear error */ alSourceUnqueueBuffers(mWindSource, 1, &buffer); error = alGetError(); if(error != AL_NO_ERROR) { LL_WARNS("OpenAL") << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << LL_ENDL; } else { alDeleteBuffers(1, &buffer); } } unprocessed += mNumEmptyWindALBuffers; while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers { ALuint buffer; alGetError(); /* clear error */ alGenBuffers(1,&buffer); if((error=alGetError()) != AL_NO_ERROR) { LL_WARNS("OpenAL") << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << LL_ENDL; break; } alBufferData(buffer, AL_FORMAT_STEREO16, mWindGen->windGenerate(mWindBuf, mWindBufSamples, 2), mWindBufBytes, mWindBufFreq); error = alGetError(); if(error != AL_NO_ERROR) LL_WARNS("OpenAL") << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << LL_ENDL; alSourceQueueBuffers(mWindSource, 1, &buffer); error = alGetError(); if(error != AL_NO_ERROR) LL_WARNS("OpenAL") << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << LL_ENDL; --mNumEmptyWindALBuffers; } int playing; alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); if(playing != AL_PLAYING) { alSourcePlay(mWindSource); LL_INFOS("OpenAL") << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << LL_ENDL; } }
int main(int argc, char* argv[]) { // // Setup the AL context. // device = alcOpenDevice(NULL); context = alcCreateContext(device, NULL); alcMakeContextCurrent(context); // // Read in the audio sample. // #ifdef EMSCRIPTEN FILE* fp = fopen("the_entertainer.wav", "rb"); #else FILE* fp = fopen("sounds/the_entertainer.wav", "rb"); #endif fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); data = (unsigned char*)malloc(size); fread(data, size, 1, fp); fclose(fp); offset = 12; // ignore the RIFF header offset += 8; // ignore the fmt header offset += 2; // ignore the format type channels = data[offset + 1] << 8; channels |= data[offset]; offset += 2; printf("Channels: %u\n", channels); frequency = data[offset + 3] << 24; frequency |= data[offset + 2] << 16; frequency |= data[offset + 1] << 8; frequency |= data[offset]; offset += 4; printf("Frequency: %u\n", frequency); offset += 6; // ignore block size and bps bits = data[offset + 1] << 8; bits |= data[offset]; offset += 2; printf("Bits: %u\n", bits); format = 0; if (bits == 8) { if (channels == 1) { format = AL_FORMAT_MONO8; } else if (channels == 2) { format = AL_FORMAT_STEREO8; } } else if (bits == 16) { if (channels == 1) { format = AL_FORMAT_MONO16; } else if (channels == 2) { format = AL_FORMAT_STEREO16; } } offset += 8; // ignore the data chunk // // Seed the buffers with some initial data. // ALuint buffers[NUM_BUFFERS]; alGenBuffers(NUM_BUFFERS, buffers); alGenSources(1, &source); ALint numBuffers = 0; while (numBuffers < NUM_BUFFERS && offset < size) { int len = size - offset; if (len > BUFFER_SIZE) { len = BUFFER_SIZE; } alBufferData(buffers[numBuffers], format, &data[offset], len, frequency); alSourceQueueBuffers(source, 1, &buffers[numBuffers]); assert(alGetError() == AL_NO_ERROR); offset += len; numBuffers++; } // // Start playing the source. // alSourcePlay(source); ALint state; alGetSourcei(source, AL_SOURCE_STATE, &state); assert(state == AL_PLAYING); alGetSourcei(source, AL_BUFFERS_QUEUED, &numBuffers); assert(numBuffers == NUM_BUFFERS); // // Cycle and refill the buffers until we're done. // #if EMSCRIPTEN emscripten_set_main_loop(iter, 0, 0); #else while (1) { iter(NULL); usleep(16); } #endif }
static ALuint generate_buffer() { ALuint buffer; alGenBuffers(1, &buffer); check_al_error("alGenBuffers"); return buffer; }
Audio::Buffer :: Buffer(){ if(Headless::enabled()) return; auto l = Audio::lock(); alGenBuffers(1, &id); }
int main(int argc, char *argv[]) { ALuint freq; ALenum format; ALvoid *data; ALsizei i, size; thread_id thread1, thread2; status_t status; /* listener parameters */ ALfloat listenerOrientation[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; ALfloat listenerPosition[] = { 0.0f, 0.0f, 0.0f }; ALfloat listenerVelocity[] = { 0.0f, 0.0f, 0.0f }; /* source parameters */ ALfloat sourcePosition[] = { 0.0f, 0.0f, 1.0f }; ALfloat sourceVelocity[] = { 0.0f, 0.0f, 0.0f }; ALfloat sourcePitch = 1.0f; ALfloat sourceGain = 1.0f; /* initialize */ print("Main: initialize"); alInit((ALint *) &argc, (ALubyte **) argv); /* create context */ print("Main: create context"); context = alcCreateContext(22050, AL_FORMAT_STEREO16, 2048); /* lock the context */ print("Main: make current"); alcMakeCurrent(context); /* create buffers and sources */ if (alGenBuffers(kNumBuffers, buffer) != kNumBuffers) quit("Can't create buffers"); if (alGenSources(kNumSources, source) != kNumSources) quit("Can't create sources"); /* load buffers with data */ alutLoadWAV(kWaveFileName, &format, &data, &size, &freq); for (i = 0; i < kNumBuffers; i++) { alBufferData(buffer[i], format, data, size, freq); } free(data); /* initialize listener */ alListenerfv(AL_POSITION, listenerPosition); alListenerfv(AL_VELOCITY, listenerVelocity); alListenerfv(AL_ORIENTATION, listenerOrientation); /* initialize sources */ for (i = 0; i < kNumSources; i++) { alSourcefv(source[i], AL_POSITION, sourcePosition); alSourcefv(source[i], AL_VELOCITY, sourceVelocity); alSourcef(source[i], AL_PITCH, sourcePitch); alSourcef(source[i], AL_GAIN, sourceGain); alSourcei(source[i], AL_BUFFER, buffer[i % kNumBuffers]); alSourcei(source[i], AL_LOOPING, AL_TRUE); } /* start the sources */ print("Main: play"); for (i = 0; i < kNumSources; i++) alSourcePlay(source[i]); /* release the context */ print("Main: release current"); alcMakeCurrent(NULL); /* spawn two threads */ print("Main: spawn thread 1"); thread1 = spawn_thread(threadFunc1, "thread 1", B_NORMAL_PRIORITY, NULL); print("Main: spawn thread 2"); thread2 = spawn_thread(threadFunc2, "thread 2", B_NORMAL_PRIORITY, NULL); /* resume the threads */ print("Main: resume thread 1"); resume_thread(thread1); print("Main: resume thread 2"); resume_thread(thread2); /* acquire context, snooze and release context */ print("Main: make current"); alcMakeCurrent(context); print("Main: snooze..."); snooze(500000); print("Main: release current"); alcMakeCurrent(NULL); /* wait until the threads end */ print("Main: wait thread 1"); wait_for_thread(thread1, &status); if (status != 0) print("Main: thread 1 failed?"); print("Main: wait thread 2"); wait_for_thread(thread2, &status); if (status != 0) print("Main: thread 2 failed?"); /* acquire the context */ print("Main: make current"); alcMakeCurrent(context); /* delete buffers and sources */ print("Main: delete sources"); alDeleteSources(kNumSources, source); print("Main: delete buffers"); alDeleteBuffers(kNumBuffers, buffer); /* release the context */ print("Main: release current"); alcMakeCurrent(NULL); /* shutdown */ print("Main: delete context"); alcDeleteContext(context); /* bye */ print("Main: bye"); alExit(); return 0; }
void SoundStream::streamData() { bool requestStop = false; { Lock lock(m_threadMutex); // Check if the thread was launched Stopped if (m_threadStartState == Stopped) { m_isStreaming = false; return; } } // Create the buffers alCheck(alGenBuffers(BufferCount, m_buffers)); for (int i = 0; i < BufferCount; ++i) m_endBuffers[i] = false; // Fill the queue requestStop = fillQueue(); // Play the sound alCheck(alSourcePlay(m_source)); { Lock lock(m_threadMutex); // Check if the thread was launched Paused if (m_threadStartState == Paused) alCheck(alSourcePause(m_source)); } for (;;) { { Lock lock(m_threadMutex); if (!m_isStreaming) break; } // The stream has been interrupted! if (SoundSource::getStatus() == Stopped) { if (!requestStop) { // Just continue alCheck(alSourcePlay(m_source)); } else { // End streaming Lock lock(m_threadMutex); m_isStreaming = false; } } // Get the number of buffers that have been processed (i.e. ready for reuse) ALint nbProcessed = 0; alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed)); while (nbProcessed--) { // Pop the first unused buffer from the queue ALuint buffer; alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); // Find its number unsigned int bufferNum = 0; for (int i = 0; i < BufferCount; ++i) if (m_buffers[i] == buffer) { bufferNum = i; break; } // Retrieve its size and add it to the samples count if (m_endBuffers[bufferNum]) { // This was the last buffer: reset the sample count m_samplesProcessed = 0; m_endBuffers[bufferNum] = false; } else { ALint size, bits; alCheck(alGetBufferi(buffer, AL_SIZE, &size)); alCheck(alGetBufferi(buffer, AL_BITS, &bits)); // Bits can be 0 if the format or parameters are corrupt, avoid division by zero if (bits == 0) { err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt " << "and initialize() has been called correctly" << std::endl; // Abort streaming (exit main loop) Lock lock(m_threadMutex); m_isStreaming = false; requestStop = true; break; } else { m_samplesProcessed += size / (bits / 8); } } // Fill it and push it back into the playing queue if (!requestStop) { if (fillAndPushBuffer(bufferNum)) requestStop = true; } } // Leave some time for the other threads if the stream is still playing if (SoundSource::getStatus() != Stopped) sleep(milliseconds(10)); } // Stop the playback alCheck(alSourceStop(m_source)); // Dequeue any buffer left in the queue clearQueue(); // Delete the buffers alCheck(alSourcei(m_source, AL_BUFFER, 0)); alCheck(alDeleteBuffers(BufferCount, m_buffers)); }
const i32 audio_updateAndPlay(MemoryArena_ *arena, AudioManager *audioManager, AudioRenderer *audioRenderer) { AudioVorbis *audio = audioRenderer->audio; if (!audio) return 0; u32 alSourceId = getSourceId(audioManager, audioRenderer); if (alIsSource(alSourceId) == AL_FALSE) { DEBUG_LOG("audio_updateAndPlay(): Update failed on invalid source id"); return -1; } ALint audioState; alGetSourcei(alSourceId, AL_SOURCE_STATE, &audioState); AL_CHECK_ERROR(); if (audioState == AL_STOPPED || audioState == AL_INITIAL) { if (audioState == AL_STOPPED) { if (audioRenderer->numPlays != AUDIO_REPEAT_INFINITE) audioRenderer->numPlays--; if (audioRenderer->numPlays == AUDIO_REPEAT_INFINITE || audioRenderer->numPlays > 0) { // TODO(doyle): Delete and recreate fixes clicking when reusing // buffers alDeleteBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); AL_CHECK_ERROR(); alGenBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); AL_CHECK_ERROR(); } else { i32 result = rendererRelease(arena, audioManager, audioRenderer); return result; } } if (audioRenderer->isStreaming) { stb_vorbis_seek_start(audio->file); for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++) { i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0}; stb_vorbis_get_samples_short_interleaved( audio->file, audio->info.channels, audioChunk, AUDIO_CHUNK_SIZE_); alBufferData(audioRenderer->bufferId[i], audioRenderer->format, audioChunk, AUDIO_CHUNK_SIZE_ * sizeof(i16), audio->info.sample_rate); AL_CHECK_ERROR(); } alSourceQueueBuffers(alSourceId, ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId); } else { alSourceQueueBuffers(alSourceId, 1, audioRenderer->bufferId); } AL_CHECK_ERROR(); alSourcePlay(alSourceId); AL_CHECK_ERROR(); } else if (audioState == AL_PLAYING) { ALint numProcessedBuffers; alGetSourcei(alSourceId, AL_BUFFERS_PROCESSED, &numProcessedBuffers); AL_CHECK_ERROR(); if (numProcessedBuffers > 0) { // TODO(doyle): Possibly wrong, we should pass in all processed buffers? ALint numBuffersToUnqueue = 1; ALuint emptyBufferId; alSourceUnqueueBuffers(alSourceId, numBuffersToUnqueue, &emptyBufferId); AL_CHECK_ERROR(); i16 audioChunk[AUDIO_CHUNK_SIZE_] = {0}; i32 sampleCount = stb_vorbis_get_samples_short_interleaved( audio->file, audio->info.channels, audioChunk, AUDIO_CHUNK_SIZE_); /* There are still samples to play */ if (sampleCount > 0) { alBufferData(emptyBufferId, audioRenderer->format, audioChunk, sampleCount * audio->info.channels * sizeof(i16), audio->info.sample_rate); AL_CHECK_ERROR(); alSourceQueueBuffers(alSourceId, 1, &emptyBufferId); AL_CHECK_ERROR(); } } } return 0; }