int main(int argc, char **argv) { ALCdevice *device; ALuint source, buffer; const char *soundname; const char *hrtfname; ALCint hrtf_state; ALCint num_hrtf; ALdouble angle; ALenum state; /* Print out usage if no file was specified */ if(argc < 2 || (strcmp(argv[1], "-hrtf") == 0 && argc < 4)) { fprintf(stderr, "Usage: %s [-hrtf <name>] <soundfile>\n", argv[0]); return 1; } /* Initialize OpenAL with the default device, and check for HRTF support. */ if(InitAL() != 0) return 1; if(strcmp(argv[1], "-hrtf") == 0) { hrtfname = argv[2]; soundname = argv[3]; } else { hrtfname = NULL; soundname = argv[1]; } device = alcGetContextsDevice(alcGetCurrentContext()); if(!alcIsExtensionPresent(device, "ALC_SOFT_HRTF")) { fprintf(stderr, "Error: ALC_SOFT_HRTF not supported\n"); CloseAL(); return 1; } /* Define a macro to help load the function pointers. */ #define LOAD_PROC(d, x) ((x) = alcGetProcAddress((d), #x)) LOAD_PROC(device, alcGetStringiSOFT); LOAD_PROC(device, alcResetDeviceSOFT); #undef LOAD_PROC /* Enumerate available HRTFs, and reset the device using one. */ alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf); if(!num_hrtf) printf("No HRTFs found\n"); else { ALCint attr[5]; ALCint index = -1; ALCint i; printf("Available HRTFs:\n"); for(i = 0; i < num_hrtf; i++) { const ALCchar *name = alcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i); printf(" %d: %s\n", i, name); /* Check if this is the HRTF the user requested. */ if(hrtfname && strcmp(name, hrtfname) == 0) index = i; } i = 0; attr[i++] = ALC_HRTF_SOFT; attr[i++] = ALC_TRUE; if(index == -1) { if(hrtfname) printf("HRTF \"%s\" not found\n", hrtfname); printf("Using default HRTF...\n"); } else { printf("Selecting HRTF %d...\n", index); attr[i++] = ALC_HRTF_ID_SOFT; attr[i++] = index; } attr[i] = 0; if(!alcResetDeviceSOFT(device, attr)) printf("Failed to reset device: %s\n", alcGetString(device, alcGetError(device))); } /* Check if HRTF is enabled, and show which is being used. */ alcGetIntegerv(device, ALC_HRTF_SOFT, 1, &hrtf_state); if(!hrtf_state) printf("HRTF not enabled!\n"); else { const ALchar *name = alcGetString(device, ALC_HRTF_SPECIFIER_SOFT); printf("HRTF enabled, using %s\n", name); } fflush(stdout); /* Load the sound into a buffer. */ buffer = LoadSound(soundname); if(!buffer) { CloseAL(); return 1; } /* Create the source to play the sound with. */ source = 0; alGenSources(1, &source); alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); alSource3f(source, AL_POSITION, 0.0f, 0.0f, -1.0f); alSourcei(source, AL_BUFFER, buffer); assert(alGetError()==AL_NO_ERROR && "Failed to setup sound source"); /* Play the sound until it finishes. */ angle = 0.0; alSourcePlay(source); do { al_nssleep(10000000); /* Rotate the source around the listener by about 1/4 cycle per second. * Only affects mono sounds. */ angle += 0.01 * M_PI * 0.5; alSource3f(source, AL_POSITION, (ALfloat)sin(angle), 0.0f, -(ALfloat)cos(angle)); alGetSourcei(source, AL_SOURCE_STATE, &state); } while(alGetError() == AL_NO_ERROR && state == AL_PLAYING); /* All done. Delete resources, and close OpenAL. */ alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); CloseAL(); return 0; }
ChannelHandle SoundManager::playAudioStream(AudioStream *audStream, SoundType type, bool disposeAfterUse) { assert((type >= 0) && (type < kSoundTypeMAX)); checkReady(); if (!audStream) throw Common::Exception("No audio stream"); Common::StackLock lock(_mutex); ChannelHandle handle = newChannel(); _channels[handle.channel] = new Channel; Channel &channel = *_channels[handle.channel]; channel.id = handle.id; channel.state = AL_PAUSED; channel.stream = audStream; channel.source = 0; channel.disposeAfterUse = disposeAfterUse; channel.type = type; channel.typeIt = _types[channel.type].list.end(); channel.gain = 1.0; try { if (!channel.stream) throw Common::Exception("Could not detect stream type"); ALenum error = AL_NO_ERROR; if (_hasSound) { // Create the source alGenSources(1, &channel.source); if ((error = alGetError()) != AL_NO_ERROR) throw Common::Exception("OpenAL error while generating sources: %X", error); // Create all needed buffers for (int i = 0; i < kOpenALBufferCount; i++) { ALuint buffer; alGenBuffers(1, &buffer); if ((error = alGetError()) != AL_NO_ERROR) throw Common::Exception("OpenAL error while generating buffers: %X", error); if (fillBuffer(channel.source, buffer, channel.stream)) { // If we could fill the buffer with data, queue it alSourceQueueBuffers(channel.source, 1, &buffer); if ((error = alGetError()) != AL_NO_ERROR) throw Common::Exception("OpenAL error while queueing buffers: %X", error); } else // If not, put it into our free list channel.freeBuffers.push_back(buffer); channel.buffers.push_back(buffer); } // Set the gain to the current sound type gain alSourcef(channel.source, AL_GAIN, _types[channel.type].gain); } // Add the channel to the correct type list _types[channel.type].list.push_back(&channel); channel.typeIt = --_types[channel.type].list.end(); } catch (...) { freeChannel(handle); throw; } return handle; }
//------------------------------------------------------------ bool ofSoundPlayerExtended::load(string fileName, bool is_stream){ string ext = ofToLower(ofFilePath::getFileExt(fileName)); if(ext != "wav" && ext != "aif" && ext != "aiff" && ext != "mp3"){ ofLogError("Sound player can only load .wav .aiff or .mp3 files"); return false; } fileName = ofToDataPath(fileName); bLoadedOk = false; bMultiPlay = false; isStreaming = is_stream; // [1] init sound systems, if necessary initialize(); // [2] try to unload any previously loaded sounds // & prevent user-created memory leaks // if they call "loadSound" repeatedly, for example unload(); ALenum format=AL_FORMAT_MONO16; if(!isStreaming || ext == "mp3"){ // mp3s don't stream cause they gotta be decoded readFile(fileName, buffer); }else{ stream(fileName, buffer); } if(channels == 0){ ofLogError("ofSoundPlayerExtended -- File not found"); return false; } int numFrames = buffer.size()/channels; if(isStreaming){ buffers.resize(channels*2); }else{ buffers.resize(channels); } alGenBuffers(buffers.size(), &buffers[0]); if(channels==1){ sources.resize(1); alGenSources(1, &sources[0]); if (alGetError() != AL_NO_ERROR){ ofLog(OF_LOG_WARNING,"ofSoundPlayerExtended: openAL error reported generating sources for " + fileName); return false; } for(int i=0; i<(int)buffers.size(); i++){ alBufferData(buffers[i],format,&buffer[0],buffer.size()*2,samplerate); if (alGetError() != AL_NO_ERROR){ ofLog(OF_LOG_ERROR,"ofSoundPlayerExtended: error creating buffer"); return false; } if(isStreaming){ stream(fileName,buffer); } } if(isStreaming){ alSourceQueueBuffers(sources[0],buffers.size(),&buffers[0]); }else{ alSourcei (sources[0], AL_BUFFER, buffers[0]); } alSourcef (sources[0], AL_PITCH, 1.0f); alSourcef (sources[0], AL_GAIN, 1.0f); alSourcef (sources[0], AL_ROLLOFF_FACTOR, 0.0); alSourcei (sources[0], AL_SOURCE_RELATIVE, AL_TRUE); }else{ vector<vector<short> > multibuffer; multibuffer.resize(channels); sources.resize(channels); alGenSources(channels, &sources[0]); if(isStreaming){ for(int s=0; s<2;s++){ for(int i=0;i<channels;i++){ multibuffer[i].resize(buffer.size()/channels); for(int j=0;j<numFrames;j++){ multibuffer[i][j] = buffer[j*channels+i]; } alBufferData(buffers[s*2+i],format,&multibuffer[i][0],buffer.size()/channels*2,samplerate); if (alGetError() != AL_NO_ERROR){ ofLog(OF_LOG_ERROR,"ofSoundPlayerExtended: error creating stereo buffers for " + fileName); return false; } alSourceQueueBuffers(sources[i],1,&buffers[s*2+i]); stream(fileName,buffer); } } }else{ for(int i=0;i<channels;i++){ multibuffer[i].resize(buffer.size()/channels); for(int j=0;j<numFrames;j++){ multibuffer[i][j] = buffer[j*channels+i]; } alBufferData(buffers[i],format,&multibuffer[i][0],buffer.size()/channels*2,samplerate); if (alGetError() != AL_NO_ERROR){ ofLog(OF_LOG_ERROR,"ofSoundPlayerExtended: error creating stereo buffers for " + fileName); return false; } alSourcei (sources[i], AL_BUFFER, buffers[i] ); } } for(int i=0;i<channels;i++){ if (alGetError() != AL_NO_ERROR){ ofLog(OF_LOG_ERROR,"ofSoundPlayerExtended: error creating stereo sources for " + fileName); return false; } // only stereo panning if(i==0){ float pos[3] = {-1,0,0}; alSourcefv(sources[i],AL_POSITION,pos); }else{ float pos[3] = {1,0,0}; alSourcefv(sources[i],AL_POSITION,pos); } alSourcef (sources[i], AL_ROLLOFF_FACTOR, 0.0); alSourcei (sources[i], AL_SOURCE_RELATIVE, AL_TRUE); } } //soundBuffer stuff--------------------- currentSoundBuffer.setNumChannels(channels); currentSoundBuffer.setSampleRate(samplerate); currentSoundBuffer.clear(); channelSoundBuffer.setNumChannels(1); channelSoundBuffer.setSampleRate(samplerate); channelSoundBuffer.clear(); //-------------------------------------- ofLogVerbose("ofSoundPlayerExtended: successfully loaded " + fileName); bLoadedOk = true; return true; }
int main() { ALCdevice* device = alcOpenDevice(NULL); ALCcontext* context = alcCreateContext(device, NULL); alcMakeContextCurrent(context); ALfloat listenerPos[] = {0.0, 0.0, 0.0}; ALfloat listenerVel[] = {0.0, 0.0, 0.0}; ALfloat listenerOri[] = {0.0, 0.0, -1.0, 0.0, 1.0, 0.0}; alListenerfv(AL_POSITION, listenerPos); alListenerfv(AL_VELOCITY, listenerVel); alListenerfv(AL_ORIENTATION, listenerOri); ALuint buffers[1]; alGenBuffers(1, buffers); FILE* source = fopen("audio.wav", "rb"); fseek(source, 0, SEEK_END); int size = ftell(source); fseek(source, 0, SEEK_SET); unsigned char* buffer = (unsigned char*) malloc(size); fread(buffer, size, 1, source); unsigned offset = 12; // ignore the RIFF header offset += 8; // ignore the fmt header offset += 2; // ignore the format type unsigned channels = buffer[offset + 1] << 8; channels |= buffer[offset]; offset += 2; printf("Channels: %u\n", channels); unsigned frequency = buffer[offset + 3] << 24; frequency |= buffer[offset + 2] << 16; frequency |= buffer[offset + 1] << 8; frequency |= buffer[offset]; offset += 4; printf("Frequency: %u\n", frequency); offset += 6; // ignore block size and bps unsigned bits = buffer[offset + 1] << 8; bits |= buffer[offset]; offset += 2; printf("Bits: %u\n", bits); ALenum 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 printf("Start offset: %d\n", offset); alBufferData(buffers[0], format, &buffer[offset], size - offset, frequency); ALuint sources[1]; alGenSources(1, sources); alSourcei(sources[0], AL_BUFFER, buffers[0]); ALint state; alGetSourcei(sources[0], AL_SOURCE_STATE, &state); assert(state == AL_INITIAL); alSourcePlay(sources[0]); alGetSourcei(sources[0], AL_SOURCE_STATE, &state); assert(state == AL_PLAYING); emscripten_async_call(playSource, reinterpret_cast<void*>(sources[0]), 700); return 0; }
void audio_thread(void *args){ ToxAV *av = args; const char *device_list, *output_device = NULL; void *audio_device = NULL; _Bool call[MAX_CALLS] = {0}, preview = 0; _Bool groups_audio[MAX_NUM_GROUPS] = {0}; int perframe = (UTOX_DEFAULT_FRAME_A * UTOX_DEFAULT_SAMPLE_RATE_A) / 1000; uint8_t buf[perframe * 2 * UTOX_DEFAULT_AUDIO_CHANNELS]; //, dest[perframe * 2 * UTOX_DEFAULT_AUDIO_CHANNELS]; memset(buf, 0, sizeof(buf)); uint8_t audio_count = 0; _Bool record_on = 0; #ifdef AUDIO_FILTERING debug("Audio Filtering"); #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES debug(" and Echo cancellation"); #endif debug(" enabled in this build\n"); #endif debug("frame size: %u\n", perframe); device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); if (device_list) { audio_device = (void*)device_list; debug("uTox audio input device list:\n"); while(*device_list) { debug("\t%s\n", device_list); postmessage(AUDIO_IN_DEVICE, UI_STRING_ID_INVALID, 0, (void*)device_list); device_list += strlen(device_list) + 1; } } postmessage(AUDIO_IN_DEVICE, STR_AUDIO_IN_NONE, 0, NULL); audio_detect(); if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { device_list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); } else { device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER); } if(device_list) { output_device = device_list; debug("uTox audio output device list:\n"); while(*device_list) { debug("\t%s\n", device_list); postmessage(AUDIO_OUT_DEVICE, 0, 0, (void*)device_list); device_list += strlen(device_list) + 1; } } device_out = alcOpenDevice(output_device); if(!device_out) { debug("alcOpenDevice() failed\n"); return; } int attrlist[] = { ALC_FREQUENCY, UTOX_DEFAULT_SAMPLE_RATE_A, ALC_INVALID }; context = alcCreateContext(device_out, attrlist); if(!alcMakeContextCurrent(context)) { debug("alcMakeContextCurrent() failed\n"); 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 = 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); } } Filter_Audio *f_a = NULL; audio_thread_init = 1; int16_t *preview_buffer = NULL; unsigned int preview_buffer_index = 0; #define PREVIEW_BUFFER_SIZE (UTOX_DEFAULT_SAMPLE_RATE_A / 2) while(1) { if(audio_thread_msg) { TOX_MSG *m = &audio_msg; if(!m->msg) { break; } switch(m->msg) { case AUDIO_SET_INPUT: { audio_device = m->data; if(record_on) { alccapturestop(device_in); alccaptureclose(device_in); } if(audio_count) { device_in = alcopencapture(audio_device); if(!device_in) { record_on = 0; } else { alccapturestart(device_in); record_on = 1; } } debug("set audio in\n"); break; } case AUDIO_SET_OUTPUT: { output_device = m->data; ALCdevice *device = alcOpenDevice(output_device); if(!device) { debug("alcOpenDevice() failed\n"); break; } ALCcontext *con = alcCreateContext(device, NULL); if(!alcMakeContextCurrent(con)) { debug("alcMakeContextCurrent() failed\n"); alcCloseDevice(device); break; } alcDestroyContext(context); alcCloseDevice(device_out); context = con; device_out = device; alGenSources(countof(source), source); alGenSources(MAX_CALLS, ringSrc); Tox *tox = toxav_get_tox(av); uint32_t num_chats = tox_count_chatlist(tox); if (num_chats != 0) { int32_t chats[num_chats]; uint32_t max = tox_get_chatlist(tox, chats, num_chats); unsigned int i; for (i = 0; i < max; ++i) { if (tox_group_get_type(tox, chats[i]) == TOX_GROUPCHAT_TYPE_AV) { GROUPCHAT *g = &group[chats[i]]; alGenSources(g->peers, g->source); } } } debug("set audio out\n"); break; } case AUDIO_PREVIEW_START: { preview = 1; audio_count++; preview_buffer = calloc(PREVIEW_BUFFER_SIZE, 2); preview_buffer_index = 0; if(!record_on) { device_in = alcopencapture(audio_device); if(device_in) { alccapturestart(device_in); record_on = 1; debug("Starting Audio Preview\n"); } } break; } case AUDIO_START: { audio_count++; if(!record_on) { device_in = alcopencapture(audio_device); if(device_in) { alccapturestart(device_in); record_on = 1; debug("Listening to audio\n"); yieldcpu(20); } } break; } case GROUP_AUDIO_CALL_START: { break; // TODO, new groups API audio_count++; groups_audio[m->param1] = 1; if(!record_on) { device_in = alcopencapture(audio_device); if(device_in) { alccapturestart(device_in); record_on = 1; debug("Starting Audio GroupCall\n"); } } break; } case AUDIO_PREVIEW_END: { preview = 0; audio_count--; free(preview_buffer); preview_buffer = NULL; if(!audio_count && record_on) { alccapturestop(device_in); alccaptureclose(device_in); record_on = 0; debug("Audio Preview Stopped\n"); } break; } case AUDIO_END: { if(!call[m->param1]) { break; } call[m->param1] = 0; audio_count--; if(!audio_count && record_on) { alccapturestop(device_in); alccaptureclose(device_in); record_on = 0; debug("stop\n"); } break; } case GROUP_AUDIO_CALL_END: { break; // TODO, new groups API if(!groups_audio[m->param1]) { break; } audio_count--; groups_audio[m->param1] = 0; if(!audio_count && record_on) { alccapturestop(device_in); alccaptureclose(device_in); record_on = 0; debug("stop\n"); } break; } case AUDIO_PLAY_RINGTONE: { if(!audible_notifications_enabled) { break; } alSourcePlay(ringSrc[m->param1]); break; } case AUDIO_STOP_RINGTONE: { ALint state; alGetSourcei(ringSrc[m->param1], AL_SOURCE_STATE, &state); if(state == AL_PLAYING) { alSourceStop(ringSrc[m->param1]); } break; } } audio_thread_msg = 0; } // TODO move this code to filter_audio.c #ifdef AUDIO_FILTERING if (!f_a && audio_filtering_enabled) { f_a = new_filter_audio(UTOX_DEFAULT_SAMPLE_RATE_A); if (!f_a) { audio_filtering_enabled = 0; debug("filter audio failed\n"); } else { debug("filter audio on\n"); } } else if (f_a && !audio_filtering_enabled) { kill_filter_audio(f_a); f_a = NULL; debug("filter audio off\n"); } #else if (audio_filtering_enabled) { audio_filtering_enabled = 0; } #endif _Bool sleep = 1; if(record_on) { ALint samples; _Bool frame = 0; /* If we have a device_in we're on linux so we can just call OpenAL, otherwise we're on something else so * we'll need to call audio_frame() to add to the buffer for us. */ if (device_in == (void*)1) { frame = audio_frame((void*)buf); if (frame) { /* We have an audio frame to use, continue without sleeping. */ sleep = 0; } } else { alcGetIntegerv(device_in, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { alcCaptureSamples(device_in, buf, perframe); frame = 1; if (samples >= perframe * 2) { sleep = 0; } } } #ifdef AUDIO_FILTERING #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES if (f_a && audio_filtering_enabled) { 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, UTOX_DEFAULT_FRAME_A); if (samples >= perframe * 2) { sleep = 0; } } } #endif #endif if (frame) { _Bool voice = 1; #ifdef AUDIO_FILTERING if (f_a) { int ret = filter_audio(f_a, (int16_t*)buf, perframe); if (ret == -1) { debug("filter audio error\n"); } if (ret == 0) { voice = 0; } } #endif /* If push to talk, we don't have to do anything */ if (!check_ptt_key()) { voice = 0; //PTT is up, send nothing. } if (preview) { if (preview_buffer_index + perframe > PREVIEW_BUFFER_SIZE) { preview_buffer_index = 0; } sourceplaybuffer(0, preview_buffer + preview_buffer_index, perframe, UTOX_DEFAULT_AUDIO_CHANNELS, UTOX_DEFAULT_SAMPLE_RATE_A); if (voice) { memcpy(preview_buffer + preview_buffer_index, buf, perframe * sizeof(int16_t)); } else { memset(preview_buffer + preview_buffer_index, 0, perframe * sizeof(int16_t)); } preview_buffer_index += perframe; } if (voice) { int i, active_call_count = 0; for(i = 0; i < UTOX_MAX_NUM_FRIENDS; i++) { if( UTOX_SEND_AUDIO(i) ) { active_call_count++; TOXAV_ERR_SEND_FRAME error = 0; toxav_audio_send_frame(av, friend[i].number, (const int16_t *)buf, perframe, UTOX_DEFAULT_AUDIO_CHANNELS, UTOX_DEFAULT_SAMPLE_RATE_A, &error); if (error) { debug("toxav_send_audio error friend == %i, error == %i\n", i, error); } else { // debug("Send a frame to friend %i\n",i); if (i >= UTOX_MAX_CALLS) { debug("We're calling more peers than allowed by UTOX_MAX_CALLS, This is a bug\n"); break; } } } } // TODO REMOVED until new groups api can be implemented. /*Tox *tox = toxav_get_tox(av); uint32_t num_chats = tox_count_chatlist(tox); if (num_chats != 0) { int32_t chats[num_chats]; uint32_t max = tox_get_chatlist(tox, chats, num_chats); for (i = 0; i < max; ++i) { if (groups_audio[chats[i]]) { toxav_group_send_audio(tox, chats[i], (int16_t *)buf, perframe, UTOX_DEFAULT_AUDIO_CHANNELS, UTOX_DEFAULT_SAMPLE_RATE_A); } } }*/ } } } if (sleep) { yieldcpu(5); } } utox_filter_audio_kill(f_a); //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); audio_thread_msg = 0; audio_thread_init = 0; debug("UTOX AUDIO:\tClean thread exit!\n"); }
int SoundSource::LoadFile(const char* file) { //Variables to store info about the WAVE file (all of them is not needed for OpenAL) char type[4]; DWORD size,chunkSize; short formatType,channels; DWORD sampleRate,avgBytesPerSec; short bytesPerSample,bitsPerSample; DWORD dataSize; //Loading of the WAVE file FILE *fp = NULL; //Create FILE pointer for the WAVE file fp=fopen(file,"rb"); //Open the WAVE file if (!fp) return endWithError("Failed to open file"); //Could not open file //Check that the WAVE file is OK fread(type,sizeof(char),4,fp); //Reads the first bytes in the file if(type[0]!='R' || type[1]!='I' || type[2]!='F' || type[3]!='F') //Should be "RIFF" return endWithError ("No RIFF"); //Not RIFF fread(&size, sizeof(DWORD),1,fp); //Continue to read the file fread(type, sizeof(char),4,fp); //Continue to read the file if (type[0]!='W' || type[1]!='A' || type[2]!='V' || type[3]!='E') //This part should be "WAVE" return endWithError("not WAVE"); //Not WAVE fread(type,sizeof(char),4,fp); //Continue to read the file if (type[0]!='f' || type[1]!='m' || type[2]!='t' || type[3]!=' ') //This part should be "fmt " return endWithError("not fmt "); //Not fmt //Now we know that the file is a acceptable WAVE file //Info about the WAVE data is now read and stored fread(&chunkSize,sizeof(DWORD),1,fp); fread(&formatType,sizeof(short),1,fp); fread(&channels,sizeof(short),1,fp); fread(&sampleRate,sizeof(DWORD),1,fp); fread(&avgBytesPerSec,sizeof(DWORD),1,fp); fread(&bytesPerSample,sizeof(short),1,fp); fread(&bitsPerSample,sizeof(short),1,fp); fread(type,sizeof(char),4,fp); if (type[0]!='d' || type[1]!='a' || type[2]!='t' || type[3]!='a') //This part should be "data" return endWithError("Missing DATA"); //not data fread(&dataSize,sizeof(DWORD),1,fp); //The size of the sound data is read //Display the info about the WAVE file cout << "Chunk Size: " << chunkSize << "\n"; cout << "Format Type: " << formatType << "\n"; cout << "Channels: " << channels << "\n"; cout << "Sample Rate: " << sampleRate << "\n"; cout << "Average Bytes Per Second: " << avgBytesPerSec << "\n"; cout << "Bytes Per Sample: " << bytesPerSample << "\n"; cout << "Bits Per Sample: " << bitsPerSample << "\n"; cout << "Data Size: " << dataSize << "\n"; soundData = new unsigned char[dataSize]; //Allocate memory for the sound data. kalla denna soundData cout << fread(soundData,sizeof(BYTE),dataSize,fp) << " bytes loaded\n"; //Read the sound data and display the //number of bytes loaded. //Should be the same as the Data Size if OK ALuint frequency = sampleRate; //The Sample Rate of the WAVE file ALenum format=0; //The audio format (bits per sample, number of channels) //Figure out the format of the WAVE file if(bitsPerSample == 8) { if(channels == 1) format = AL_FORMAT_MONO8; else if(channels == 2) format = AL_FORMAT_STEREO8; } else if(bitsPerSample == 16) { if(channels == 1) format = AL_FORMAT_MONO16; else if(channels == 2) format = AL_FORMAT_STEREO16; } if(!format) return endWithError("Wrong BitPerSample"); //Not valid format alGenBuffers(1, &mBuffer); //Generate one OpenAL Buffer and link to "buffer" alGenSources(1, &mSource); //Generate one OpenAL Source and link to "source" if(alGetError() != AL_NO_ERROR) return endWithError("Error GenSource"); //Error during buffer/source generation alBufferData(mBuffer, format, soundData, dataSize, frequency); //Store the sound data in the OpenAL Buffer if(alGetError() != AL_NO_ERROR) return endWithError("Error loading ALBuffer"); //Error during buffer loading fclose(fp); }
/* * ALboolean LoadALData() * * This function will load our sample data from the disk using the alut * utility and send the data into OpenAL as a buffer. A source is then * also created to play that buffer. */ int LoadSoundBuffers() { int theerror=0; // Variables to load into. if (total_loaded_buffers==0) { fprintf(stderr,"No Sounds to load!\n"); return 0; } ALenum format; ALsizei size; ALvoid* data; ALsizei freq; ALboolean loop; // Load wav data into buffers. alGenBuffers(total_loaded_buffers, Buffers); if(alGetError() != AL_NO_ERROR) { fprintf(stderr,"Error Generating Buffers!\n"); return 0; } for (unsigned int i=0; i<total_loaded_buffers; i++) { alutLoadWAVFile((ALbyte *)filenames[i], &format, &data, &size, &freq, &loop); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error (%u) loading Wav sound Buffer %u %s\n",theerror,i,filenames[i]); } alBufferData(Buffers[i], format, data, size, freq); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error (%u) loading Wav sound Buffer %u %s\n",theerror,i,filenames[i]); } alutUnloadWAV(format, data, size, freq); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error (%u) loading Wav sound Buffer %u %s\n",theerror,i,filenames[i]); } free(filenames[i]); /* Release memory for filename */ } // Bind buffers into audio sources. alGenSources(NUM_SOURCES, Sources); theerror=alGetError(); if(theerror != AL_NO_ERROR) { fprintf(stderr,"Error Generating Sources (%u)!\n",theerror); return 0; } for (unsigned int i=0; i<total_loaded_buffers; i++) { /*alGenSources( 1, &Sources[i] ); theerror=alGetError(); if(theerror != AL_NO_ERROR) { cout<<"Error Generating Sources ("<<theerror<<")!\n"; return false; } */ alSourcei (Sources[i], AL_BUFFER, Buffers[i] ); alSourcef (Sources[i], AL_PITCH, 1.0f ); alSourcef (Sources[i], AL_GAIN, 1.0f ); alSourcefv(Sources[i], AL_POSITION, SourcesPos[i]); alSourcefv(Sources[i], AL_VELOCITY, SourcesVel[i]); alSourcei (Sources[i], AL_LOOPING, AL_FALSE ); } // Bind buffers into audio sources. // Do another error check and return. if(alGetError() != AL_NO_ERROR) return 0; SetListenerValues(); return 1; }
//------------------------------------------------------------------------------ bool CGUIMusicData_openal::LoadOggFile( const CGUIString& rFilename ) const { //open file FILE *pFile = fopen( rFilename.c_str(), "rb" ); if( !pFile) { return false; } ov_callbacks sCallbacks; sCallbacks.read_func = ov_read_func; sCallbacks.seek_func = ov_seek_func; sCallbacks.close_func = ov_close_func; sCallbacks.tell_func = ov_tell_func; if (ov_open_callbacks(pFile, &m_aVorbisFile, NULL, 0, sCallbacks) != 0) { fclose( pFile ); return false; } // Get some information about the file (Channels, Format, and Frequency) if( false == GetOggVorbisInfo( &m_aVorbisFile, &m_nFrequency, &m_nFormat, &m_nFormat, &m_nBufferSize ) ) { ov_clear(&m_aVorbisFile); return false; } // Allocate a buffer to be used to store decoded data for all Buffers m_pDecodeBuffer = (char*)malloc(m_nBufferSize); if ( !m_pDecodeBuffer ) { ov_clear(&m_aVorbisFile); return false; } // Generate a Source to playback the Buffers alGenSources(1, &m_nSourceId); if (alGetError() != AL_NO_ERROR) { return false; } // Generate some AL Buffers for streaming alGenBuffers( GUI_MUSIC_NUMBUFFERS, m_nBuffers ); if (alGetError() != AL_NO_ERROR) { return false; } // Fill all the Buffers with decoded audio data from the OggVorbis file for (int iLoop = 0; iLoop < GUI_MUSIC_NUMBUFFERS; iLoop++) { unsigned long ulBytesWritten = DecodeOggVorbis(&m_aVorbisFile, m_pDecodeBuffer, m_nBufferSize, m_nChannels); if (ulBytesWritten) { alBufferData(m_nBuffers[iLoop], m_nFormat, m_pDecodeBuffer, ulBytesWritten, m_nFrequency); alSourceQueueBuffers(m_nSourceId, 1, &m_nBuffers[iLoop]); } } return true; }
ALuint Audio::RegisterSource() { ALuint source; alGenSources((ALuint)1, &source); return source; }
SoundSource::SoundSource() { id.emplace(); AL(alGenSources(1, &*id)); }
void GLApplication::initialize() { if (!windowManager || !windowManager->initialize(800, 700, "Window GLFW", false)) { this->destroy(); exit(-1); } glViewport(0, 0, WindowManager::screenWidth, WindowManager::screenHeight); glClearColor(0.2f, 0.2f, 0.2f, 0.0f); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); shader.initialize("Shaders/lightingSpecularMap.vs", "Shaders/lightingSpecularMap.fs"); sphere.init(); sphere.load(); textureDifuse.load(); textureSpecular.load(); alutInit(0, NULL); alListenerfv(AL_POSITION, listenerPos); alListenerfv(AL_VELOCITY, listenerVel); alListenerfv(AL_ORIENTATION, listenerOri); alGetError(); // clear any error messages if (alGetError() != AL_NO_ERROR) { printf("- Error creating buffers !!\n"); exit(1); } else { printf("init() - No errors yet."); } // Generate buffers, or else no sound will happen! alGenBuffers(NUM_BUFFERS, buffer); buffer[0] = alutCreateBufferFromFile("sounds/lawyer1.wav"); //buffer[0] = alutCreateBufferHelloWorld(); alGetError(); /* clear error */ alGenSources(NUM_SOURCES, source); if (alGetError() != AL_NO_ERROR) { printf("- Error creating sources !!\n"); exit(2); } else { printf("init - no errors after alGenSources\n"); } alSourcef(source[0], AL_PITCH, 1.0f); alSourcef(source[0], AL_GAIN, 1.0f); alSourcefv(source[0], AL_POSITION, source0Pos); alSourcefv(source[0], AL_VELOCITY, source0Vel); alSourcei(source[0], AL_BUFFER, buffer[0]); alSourcei(source[0], AL_LOOPING, AL_TRUE); alSourcef(source[0], AL_MAX_DISTANCE, 1200); objModel.loadModel("objects/nanosuit/nanosuit.obj"); /*alSourcef(source[1], AL_PITCH, 1.0f); alSourcef(source[1], AL_GAIN, 1.0f); alSourcefv(source[1], AL_POSITION, source1Pos); alSourcefv(source[1], AL_VELOCITY, source1Vel); alSourcei(source[1], AL_BUFFER, buffer[1]); alSourcei(source[1], AL_LOOPING, AL_TRUE); alSourcef(source[2], AL_PITCH, 1.0f); alSourcef(source[2], AL_GAIN, 1.0f); alSourcefv(source[2], AL_POSITION, source2Pos); alSourcefv(source[2], AL_VELOCITY, source2Vel); alSourcei(source[2], AL_BUFFER, buffer[2]); alSourcei(source[2], AL_LOOPING, AL_TRUE);*/ }
void ChannelStream::Open( int channels, int bits, int samplerate ) { if (started) return; VERBOSE("ChannelStream Open"); if (channels == 1) { format = AL_FORMAT_MONO16; if (bits == 8) format = AL_FORMAT_MONO8; } else if (channels == 2) { format = AL_FORMAT_STEREO16; if (bits == 8) format = AL_FORMAT_STEREO8; } Check(); alGenBuffers(NUM_BUFFERS, buffers); Check("opengenbuf"); alGenSources(1, &source); Check("opengensource"); alSourcei(source, AL_BUFFER, AL_NONE); Check("buffer reset"); // Debug::Log("AUDIO: Opening Audio Channel: " + StringOf(samplerate) + "hz w/ " + StringOf(bits) + "bits w/ " + StringOf(channels) + " channels (ALformat:" + StringOf(format) +") SOURCE ID: " + StringOf(source)); Check("openbufferdata"); alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0); /*alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0);*/ this->lastVol = 1.0; alSourcef(source, AL_GAIN, 1.0); alSourcef(source, AL_PITCH, 1.0); alSourcei(source, AL_LOOPING, AL_FALSE); Check("opensetsource"); alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(source, AL_ROLLOFF_FACTOR, 0); Check("opensetsource2"); this->samplerate = samplerate; this->started = true; this->startBuffer = 0; this->startedPlaying = false; this->pausePos = 0; this->playOffset = 0; this->playStart = 0; }
/** 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)(const void *), const void *user_data, size_t streamBufferSize, unsigned int buffer_count) { AUDIO_STREAM *stream; ALuint *buffers = (ALuint *)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 nullptr; } stream = (AUDIO_STREAM *)malloc(sizeof(AUDIO_STREAM)); if (stream == nullptr) { debug(LOG_FATAL, "sound_PlayStream: Out of memory"); abort(); return nullptr; } // 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 nullptr; } stream->fileHandle = fileHandle; stream->decoder = sound_CreateOggVorbisDecoder(stream->fileHandle, false); if (stream->decoder == nullptr) { debug(LOG_ERROR, "sound_PlayStream: Failed to open audio file for decoding"); free(stream); return nullptr; } 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 nullptr; } // 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; }
//* // ======================================================================================================================= // ======================================================================================================================= // bool sound_Play2DSample(TRACK *psTrack, AUDIO_SAMPLE *psSample, bool bQueued) { ALfloat zero[3] = { 0.0, 0.0, 0.0 }; ALfloat volume; ALint error; if (sfx_volume == 0.0) { return false; } volume = ((float)psTrack->iVol / 100.0f); // each object can have OWN volume! psSample->fVol = volume; // save computed volume volume *= sfx_volume; // and now take into account the Users sound Prefs. // We can't hear it, so don't bother creating it. if (volume == 0.0f) { return false; } // Clear error codes alGetError(); alGenSources(1, &(psSample->iSample)); error = sound_GetError(); if (error != AL_NO_ERROR) { /* FIXME: We run out of OpenAL sources very quickly, so we * should handle the case where we've ran out of them. * Currently we don't do this, causing some unpleasant side * effects, e.g. crashing... */ } alSourcef(psSample->iSample, AL_PITCH, 1.0f); alSourcef(psSample->iSample, AL_GAIN, volume); alSourcefv(psSample->iSample, AL_POSITION, zero); alSourcefv(psSample->iSample, AL_VELOCITY, zero); alSourcei(psSample->iSample, AL_BUFFER, psTrack->iBufferName); alSourcei(psSample->iSample, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(psSample->iSample, AL_LOOPING, (sound_SetupChannel(psSample)) ? AL_TRUE : AL_FALSE); // NOTE: this is only useful for debugging. #ifdef DEBUG psSample->is3d = false; psSample->isLooping = sound_TrackLooped(psSample->iTrack) ? AL_TRUE : AL_FALSE; memcpy(psSample->filename, psTrack->fileName, strlen(psTrack->fileName)); psSample->filename[strlen(psTrack->fileName)] = '\0'; #endif // Clear error codes alGetError(); alSourcePlay(psSample->iSample); sound_GetError(); if (bQueued) { current_queue_sample = psSample->iSample; } else if (current_queue_sample == psSample->iSample) { current_queue_sample = -1; } return true; }
void boot_init(int* argc, char** argv) { int error; fail_if(glfwInit() == false); // OpenGL version 3 glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 0); // No window resize glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, true); // 400% gameboy scale, 5 bit rgb with 1 bit alpha, 8 bit z buffer fail_if(glfwOpenWindow(160 * 4, 144 * 4, 5, 5, 5, 1, 8, 0, GLFW_WINDOW) == false); glfwSetWindowTitle(""); glfwEnable(GLFW_AUTO_POLL_EVENTS); // Automatically poll input on swap glfwSwapInterval(1); // 0: vsync off, 1: vsync on printf("Renderer: %s\n", glGetString(GL_RENDERER)); printf("GL Version: %s\n", glGetString(GL_VERSION)); printf("Using GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); error = glewInit(); if (error != GLEW_OK) { fprintf(stderr, "GLEW error: %s\n", glewGetErrorString(error)); } printf("GL Extension Wrangler: %s\n", glewGetString(GLEW_VERSION)); // Load audio fail_if(alutInit(argc, argv) == false); glClearColor(206.0/255.0, 230.0/255.0, 165.0/255.0, 1.0f); glEnable(GL_SCISSOR_TEST); // For geom culling // transparency glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // z-buffer glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // Set up perspective glOrtho(0, 160, 144, 0, -1.0, 1.0); glDepthRange(-1.0f, 1.0f); glViewport(0, 0, 160 * 4, 144 * 4); // This is where Ill put the logo thing unsigned logo = bitmap_load("bmp/logo.bmp"); unsigned logo_vbo; float t0, t1, dt; float logo_x = 16, logo_y = -80; float logo_v[] = { 0, 0, 0, 1.0 - 0, 0, 128, 0, 1.0 - 1, 128, 128, 1, 1.0 - 1, 128, 0, 1, 1.0 - 0, }; glGenBuffers(1, &logo_vbo); glBindBuffer(GL_ARRAY_BUFFER, logo_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(logo_v)*sizeof(float), logo_v, GL_STATIC_DRAW); Pipeline* logo_program = pipeline_new( shader_new(SHADER_VERTEX, "shader/logo.vert"), shader_new(SHADER_FRAGMENT, "shader/logo.frag")); pipeline_attribute(logo_program, "coord", 0); pipeline_attribute(logo_program, "st", 1); pipeline_uniform(logo_program, "pos", 0); pipeline_uniform(logo_program, "tex", 1); glUseProgram(logo_program->id); // Bind the logo to texture 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, logo); glUniform1i(logo_program->uniform[1], 0); // Bind logo vbo glBindBuffer(GL_ARRAY_BUFFER, logo_vbo); glEnableVertexAttribArray(logo_program->attribute[0]); glVertexAttribPointer(logo_program->attribute[0], 2, GL_FLOAT, false, 4*sizeof(float), (void*)0); glEnableVertexAttribArray(logo_program->attribute[1]); glVertexAttribPointer(logo_program->attribute[1], 2, GL_FLOAT, false, 4*sizeof(float), (void*)(2 * sizeof(float))); // load sound unsigned sound_source; alGenSources(1, &sound_source); Sound* ding = sound_load("sound/ding.ogg"); alSourcei(sound_source, AL_BUFFER, ding->buffer); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glfwSwapBuffers(); sleep(1); t0 = glfwGetTime(); while (logo_y < 8) { t1 = glfwGetTime(); dt = t1 - t0; t0 = t1; logo_y += 50 * dt; glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glUniform2f(logo_program->uniform[0], roundf(logo_x), roundf(logo_y)); // Render logo glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glfwSwapBuffers(); } alSourcePlay(sound_source); glDisableVertexAttribArray(logo_program->attribute[0]); glDisableVertexAttribArray(logo_program->attribute[1]); sleep(1); }
ALboolean LoadALData() { // Variables to load into. ALenum format; ALsizei size; ALvoid* data; ALsizei freq; ALboolean loop; // Load wav data into buffers. alGenBuffers(NUM_BUFFERS, Buffers); if(alGetError() != AL_NO_ERROR) return AL_FALSE; alutLoadWAVFile("sound/hit.wav", &format, &data, &size, &freq, &loop); alBufferData(Buffers[hit], format, data, size, freq); alutUnloadWAV(format, data, size, freq); // alutLoadWAVFile("wavdata/Gun1.wav", &format, &data, &size, &freq, &loop); // alBufferData(Buffers[GUN1], format, data, size, freq); // alutUnloadWAV(format, data, size, freq); // alutLoadWAVFile("wavdata/Gun2.wav", &format, &data, &size, &freq, &loop); // alBufferData(Buffers[GUN2], format, data, size, freq); // alutUnloadWAV(format, data, size, freq); //alutLoadWAVFile("sound/dung.wav", &format, &data, &size, &freq, &loop); //alBufferData(Buffers[dung], format, data, size, freq); //alutUnloadWAV(format, data, size, freq); // Bind buffers into audio sources. alGenSources(NUM_SOURCES, Sources); if(alGetError() != AL_NO_ERROR) return AL_FALSE; //alSourcei (Sources[dung], AL_BUFFER, Buffers[dung] ); //alSourcef (Sources[dung], AL_PITCH, 1.0f ); //alSourcef (Sources[dung], AL_GAIN, 1.0f ); //alSourcefv(Sources[dung], AL_POSITION, SourcesPos[dung]); //alSourcefv(Sources[dung], AL_VELOCITY, SourcesVel[dung]); //alSourcei (Sources[dung], AL_LOOPING, AL_TRUE ); alSourcei (Sources[hit], AL_BUFFER, Buffers[hit] ); alSourcef (Sources[hit], AL_PITCH, 1.0f ); alSourcef (Sources[hit], AL_GAIN, 1.0f ); alSourcefv(Sources[hit], AL_POSITION, SourcesPos[hit]); alSourcefv(Sources[hit], AL_VELOCITY, SourcesVel[hit]); alSourcei (Sources[hit], AL_LOOPING, AL_FALSE ); /* alSourcei (Sources[GUN1], AL_BUFFER, Buffers[GUN1] ); alSourcef (Sources[GUN1], AL_PITCH, 1.0f ); alSourcef (Sources[GUN1], AL_GAIN, 1.0f ); alSourcefv(Sources[GUN1], AL_POSITION, SourcesPos[GUN1]); alSourcefv(Sources[GUN1], AL_VELOCITY, SourcesVel[GUN1]); alSourcei (Sources[GUN1], AL_LOOPING, AL_FALSE ); alSourcei (Sources[GUN2], AL_BUFFER, Buffers[GUN2] ); alSourcef (Sources[GUN2], AL_PITCH, 1.0f ); alSourcef (Sources[GUN2], AL_GAIN, 1.0f ); alSourcefv(Sources[GUN2], AL_POSITION, SourcesPos[GUN2]); alSourcefv(Sources[GUN2], AL_VELOCITY, SourcesVel[GUN2]); alSourcei (Sources[GUN2], AL_LOOPING, AL_FALSE ); */ // Do another error check and return. if(alGetError() != AL_NO_ERROR) return AL_FALSE; return AL_TRUE; }
//------------------------------------------------------------ bool ofOpenALSoundPlayer::loadSound(string fileName, bool is_stream){ fileName = ofToDataPath(fileName); bMultiPlay = false; isStreaming = is_stream; int err = AL_NO_ERROR; // [1] init sound systems, if necessary initialize(); // [2] try to unload any previously loaded sounds // & prevent user-created memory leaks // if they call "loadSound" repeatedly, for example unloadSound(); ALenum format=AL_FORMAT_MONO16; bLoadedOk = false; if(!isStreaming){ readFile(fileName, buffer); }else{ stream(fileName, buffer); } int numFrames = buffer.size()/channels; if(isStreaming){ buffers.resize(channels*2); }else{ buffers.resize(channels); } alGenBuffers(buffers.size(), &buffers[0]); if(channels==1){ sources.resize(1); alGenSources(1, &sources[0]); err = alGetError(); if (err != AL_NO_ERROR){ ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't generate source for \"" << fileName << "\": " << (int) err << " " << getALErrorString(err); return false; } for(int i=0; i<(int)buffers.size(); i++){ alBufferData(buffers[i],format,&buffer[0],buffer.size()*2,samplerate); err = alGetError(); if (err != AL_NO_ERROR){ ofLogError("ofOpenALSoundPlayer:") << "loadSound(): couldn't create buffer for \"" << fileName << "\": " << (int) err << " " << getALErrorString(err); return false; } if(isStreaming){ stream(fileName,buffer); } } if(isStreaming){ alSourceQueueBuffers(sources[0],buffers.size(),&buffers[0]); }else{ alSourcei (sources[0], AL_BUFFER, buffers[0]); } alSourcef (sources[0], AL_PITCH, 1.0f); alSourcef (sources[0], AL_GAIN, 1.0f); alSourcef (sources[0], AL_ROLLOFF_FACTOR, 0.0); alSourcei (sources[0], AL_SOURCE_RELATIVE, AL_TRUE); }else{ vector<vector<short> > multibuffer; multibuffer.resize(channels); sources.resize(channels); alGenSources(channels, &sources[0]); if(isStreaming){ for(int s=0; s<2;s++){ for(int i=0;i<channels;i++){ multibuffer[i].resize(buffer.size()/channels); for(int j=0;j<numFrames;j++){ multibuffer[i][j] = buffer[j*channels+i]; } alBufferData(buffers[s*2+i],format,&multibuffer[i][0],buffer.size()/channels*2,samplerate); err = alGetError(); if ( err != AL_NO_ERROR){ ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create stereo buffers for \"" << fileName << "\": " << (int) err << " " << getALErrorString(err); return false; } alSourceQueueBuffers(sources[i],1,&buffers[s*2+i]); stream(fileName,buffer); } } }else{ for(int i=0;i<channels;i++){ multibuffer[i].resize(buffer.size()/channels); for(int j=0;j<numFrames;j++){ multibuffer[i][j] = buffer[j*channels+i]; } alBufferData(buffers[i],format,&multibuffer[i][0],buffer.size()/channels*2,samplerate); err = alGetError(); if (err != AL_NO_ERROR){ ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create stereo buffers for \"" << fileName << "\": " << (int) err << " " << getALErrorString(err); return false; } alSourcei (sources[i], AL_BUFFER, buffers[i] ); } } for(int i=0;i<channels;i++){ err = alGetError(); if (err != AL_NO_ERROR){ ofLogError("ofOpenALSoundPlayer") << "loadSound(): couldn't create stereo sources for \"" << fileName << "\": " << (int) err << " " << getALErrorString(err); return false; } // only stereo panning if(i==0){ float pos[3] = {-1,0,0}; alSourcefv(sources[i],AL_POSITION,pos); }else{ float pos[3] = {1,0,0}; alSourcefv(sources[i],AL_POSITION,pos); } alSourcef (sources[i], AL_ROLLOFF_FACTOR, 0.0); alSourcei (sources[i], AL_SOURCE_RELATIVE, AL_TRUE); } } bLoadedOk = true; return bLoadedOk; }
void audio_output::init(int i) { if (!_initialized) { if (i < 0) { if (!(_device = alcOpenDevice(NULL))) { throw exc(_("No OpenAL device available.")); } } else if (i >= static_cast<int>(_devices.size())) { throw exc(str::asprintf(_("OpenAL device '%s' is not available."), _("unknown"))); } else { if (!(_device = alcOpenDevice(_devices[i].c_str()))) { throw exc(str::asprintf(_("OpenAL device '%s' is not available."), _devices[i].c_str())); } } if (!(_context = alcCreateContext(_device, NULL))) { alcCloseDevice(_device); throw exc(_("No OpenAL context available.")); } alcMakeContextCurrent(_context); set_openal_versions(); _buffers.resize(_num_buffers); alGenBuffers(_num_buffers, &(_buffers[0])); if (alGetError() != AL_NO_ERROR) { alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); throw exc(_("Cannot create OpenAL buffers.")); } alGenSources(1, &_source); if (alGetError() != AL_NO_ERROR) { alDeleteBuffers(_num_buffers, &(_buffers[0])); alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); throw exc(_("Cannot create OpenAL source.")); } /* Comment from alffmpeg.c: * "Set parameters so mono sources won't distance attenuate" */ alSourcei(_source, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(_source, AL_ROLLOFF_FACTOR, 0); if (alGetError() != AL_NO_ERROR) { alDeleteSources(1, &_source); alDeleteBuffers(_num_buffers, &(_buffers[0])); alcMakeContextCurrent(NULL); alcDestroyContext(_context); alcCloseDevice(_device); throw exc(_("Cannot set OpenAL source parameters.")); } _state = 0; _initialized = true; } }
OpenalSoundInterface::OpenalSoundInterface(float sampling_rate, int n_channels): SoundInterface (sampling_rate, n_channels) { car_src = NULL; ALfloat far_away[] = { 0.0f, 0.0f, 1000.0f }; ALfloat zeroes[] = { 0.0f, 0.0f, 0.0f }; ALfloat front[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; dev = alcOpenDevice( NULL ); if( dev == NULL ) { throw ("Could not open device"); } // Last zero is termination of the array, I think the current official beat SDK ignores that. // ALCint attr[] = { ALC_MONO_SOURCES, 1024, ALC_STEREO_SOURCES, 0, 0}; cc = alcCreateContext( dev, NULL); if(cc == NULL) { alcCloseDevice( dev ); throw ("Could not create context."); } alcMakeContextCurrent( cc ); alcGetError(dev); alGetError(); // Figure out the number of possible sources, watch out for an API update, perhaps // one can get that easier later with al(c)GetInteger (I'm sure that there is no way to // query this now) or even request a number with the context. const int MAX_SOURCES = 1024; int sources; ALuint sourcelist[MAX_SOURCES]; for (sources = 0; sources < MAX_SOURCES; sources++) { alGenSources(1, &sourcelist[sources]); if (alGetError() != AL_NO_ERROR) { break; } } int clear; for (clear = 0; clear < sources; clear++) { if (alIsSource(sourcelist[clear])) { alDeleteSources(1, &sourcelist[clear]); if (alGetError() != AL_NO_ERROR) { printf("Error in probing OpenAL sources.\n"); } } else { printf("Error in probing OpenAL sources.\n"); } } OSI_MAX_SOURCES = sources; OSI_MAX_STATIC_SOURCES = MAX(0, OSI_MAX_SOURCES - OSI_MIN_DYNAMIC_SOURCES); // Figure out the number of buffers. int buffers; ALuint bufferlist[MAX_SOURCES]; for (buffers = 0; buffers < MAX_SOURCES; buffers++) { alGenBuffers(1, &bufferlist[buffers]); if (alGetError() != AL_NO_ERROR) { break; } } for (clear = 0; clear < buffers; clear++) { if (alIsBuffer(bufferlist[clear])) { alDeleteBuffers(1, &bufferlist[clear]); if (alGetError() != AL_NO_ERROR) { printf("Error in probing OpenAL buffers.\n"); } } else { printf("Error in probing OpenAL buffers.\n"); } } OSI_MAX_BUFFERS = buffers; printf("OpenAL backend info:\n Vendor: %s\n Renderer: %s\n Version: %s\n", alGetString(AL_VENDOR), alGetString(AL_RENDERER), alGetString(AL_VERSION)); printf(" Available sources: %d%s\n", OSI_MAX_SOURCES, (sources >= MAX_SOURCES) ? " or more" : ""); printf(" Available buffers: %d%s\n", OSI_MAX_BUFFERS, (buffers >= MAX_SOURCES) ? " or more" : ""); alDistanceModel ( AL_INVERSE_DISTANCE ); int error = alGetError(); if (error != AL_NO_ERROR) { printf("OpenAL Error: %d alDistanceModel\n", error); } alDopplerFactor (1.0f); //alSpeedOfSound (SPEED_OF_SOUND); // not defined in linux yet. alDopplerVelocity (SPEED_OF_SOUND); error = alGetError(); if (error != AL_NO_ERROR) { printf("OpenAL Error: %d alDopplerX\n", error); } alListenerfv(AL_POSITION, far_away ); alListenerfv(AL_VELOCITY, zeroes ); alListenerfv(AL_ORIENTATION, front ); error = alGetError(); if (error != AL_NO_ERROR) { printf("OpenAL Error: %d alListenerfv\n", error); } engpri = NULL; global_gain = 1.0f; // initialise mappings grass.schar = &CarSoundData::grass; grass_skid.schar = &CarSoundData::grass_skid; road.schar = &CarSoundData::road; metal_skid.schar = &CarSoundData::drag_collision; backfire_loop.schar = &CarSoundData::engine_backfire; turbo.schar = &CarSoundData::turbo; axle.schar = &CarSoundData::axle; n_static_sources_in_use = 0; }
Source::Source() { alGenSources(1, &source);ALDEBUG_THROW; }
void cargarSonido (void) { ALsizei tamanyo; Uint8 *datos; ALfloat velocity[3]= { 0.0, 0.0, 0.0 }; ALfloat pitch = 1.0, gain = 1.0; SDL_AudioSpec wav_spec; // reservar memoria para los sonidos son = (sonidos *) malloc (sizeof (sonidos)); // generar el buffer del rayo alGenBuffers (1, &son->bufferRayo); // cargar el sonido de un fichero SDL_LoadWAV ("blaster02.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferRayo, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente del rayo alGenSources (1, &son->fuenteRayo); // inicializar los valores de la fuente alSourcef (son->fuenteRayo, AL_PITCH, pitch); alSourcef (son->fuenteRayo, AL_GAIN, gain); alSourcefv (son->fuenteRayo, AL_VELOCITY, velocity); alSourcei (son->fuenteRayo, AL_BUFFER, son->bufferRayo); alSourcei (son->fuenteRayo, AL_LOOPING, AL_FALSE); // generar el buffer de ganas alGenBuffers (1, &son->bufferGanas); // cargar el sonido de un fichero SDL_LoadWAV ("chewie04.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferGanas, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de ganas alGenSources (1, &son->fuenteGanas); // inicializar los valores de la fuente alSourcef (son->fuenteGanas, AL_PITCH, pitch); alSourcef (son->fuenteGanas, AL_GAIN, gain); alSourcefv (son->fuenteGanas, AL_VELOCITY, velocity); alSourcei (son->fuenteGanas, AL_BUFFER, son->bufferGanas); alSourcei (son->fuenteGanas, AL_LOOPING, AL_FALSE); // generar el buffer de pierdes alGenBuffers (1, &son->bufferPierdes); // cargar el sonido de un fichero SDL_LoadWAV ("chewie03.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferPierdes, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de pierdes alGenSources (1, &son->fuentePierdes); // inicializar los valores de la fuente alSourcef (son->fuentePierdes, AL_PITCH, pitch); alSourcef (son->fuentePierdes, AL_GAIN, gain); alSourcefv (son->fuentePierdes, AL_VELOCITY, velocity); alSourcei (son->fuentePierdes, AL_BUFFER, son->bufferPierdes); alSourcei (son->fuentePierdes, AL_LOOPING, AL_FALSE); // generar el buffer de acierto alGenBuffers (1, &son->bufferAcierto); // cargar el sonido de un fichero SDL_LoadWAV ("expl02.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferAcierto, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente del acierto alGenSources (1, &son->fuenteAcierto); // inicializar los valores de la fuente alSourcef (son->fuenteAcierto, AL_PITCH, pitch); alSourcef (son->fuenteAcierto, AL_GAIN, gain); alSourcefv (son->fuenteAcierto, AL_VELOCITY, velocity); alSourcei (son->fuenteAcierto, AL_BUFFER, son->bufferAcierto); alSourcei (son->fuenteAcierto, AL_LOOPING, AL_FALSE); // generar el buffer de indy alGenBuffers (1, &son->bufferIndy); // cargar el sonido de un fichero SDL_LoadWAV ("indy.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferIndy, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de indy alGenSources (1, &son->fuenteIndy); // inicializar los valores de la fuente alSourcef (son->fuenteIndy, AL_PITCH, pitch); alSourcef (son->fuenteIndy, AL_GAIN, gain); alSourcefv (son->fuenteIndy, AL_VELOCITY, velocity); alSourcei (son->fuenteIndy, AL_BUFFER, son->bufferIndy); alSourcei (son->fuenteIndy, AL_LOOPING, AL_FALSE); // generar el buffer de rebote 1 alGenBuffers (1, &son->bufferRebote1); // cargar el sonido de un fichero SDL_LoadWAV ("bounce1.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferRebote1, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de rebote 1 alGenSources (1, &son->fuenteRebote1); // inicializar los valores de la fuente alSourcef (son->fuenteRebote1, AL_PITCH, pitch); alSourcef (son->fuenteRebote1, AL_GAIN, gain); alSourcefv (son->fuenteRebote1, AL_VELOCITY, velocity); alSourcei (son->fuenteRebote1, AL_BUFFER, son->bufferRebote1); alSourcei (son->fuenteRebote1, AL_LOOPING, AL_FALSE); // generar el buffer de rebote 2 alGenBuffers (1, &son->bufferRebote2); // cargar el sonido de un fichero SDL_LoadWAV ("bounce2.wav", &wav_spec, &datos, &tamanyo); alBufferData (son->bufferRebote2, AL_FORMAT_STEREO8, datos, tamanyo, wav_spec.freq); SDL_FreeWAV (datos); // generar la fuente de rebote 2 alGenSources (1, &son->fuenteRebote2); // inicializar los valores de la fuente alSourcef (son->fuenteRebote2, AL_PITCH, pitch); alSourcef (son->fuenteRebote2, AL_GAIN, gain); alSourcefv (son->fuenteRebote2, AL_VELOCITY, velocity); alSourcei (son->fuenteRebote2, AL_BUFFER, son->bufferRebote2); alSourcei (son->fuenteRebote2, AL_LOOPING, AL_FALSE); // inicializar los valores del oyente alListenerfv (AL_VELOCITY, velocity); }
void *decode_audio_thread(void *arg) { INFO("Started decode audio thread!"); av_session_t *_phone = arg; _phone->running_decaud = 1; //int recved_size; //uint8_t dest [RTP_PAYLOAD_SIZE]; int frame_size = AUDIO_FRAME_SIZE; //int data_size; ALCdevice *dev; ALCcontext *ctx; ALuint source, *buffers; dev = alcOpenDevice(NULL); ctx = alcCreateContext(dev, NULL); alcMakeContextCurrent(ctx); int openal_buffers = 5; buffers = calloc(sizeof(ALuint) * openal_buffers, 1); alGenBuffers(openal_buffers, buffers); alGenSources((ALuint)1, &source); alSourcei(source, AL_LOOPING, AL_FALSE); ALuint buffer; ALint ready; uint16_t zeros[frame_size]; memset(zeros, 0, frame_size); int16_t PCM[frame_size]; int i; for (i = 0; i < openal_buffers; ++i) { alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); } alSourceQueueBuffers(source, openal_buffers, buffers); alSourcePlay(source); if (alGetError() != AL_NO_ERROR) { fprintf(stderr, "Error starting audio\n"); goto ending; } int dec_frame_len = 0; while (_phone->running_decaud) { alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); if (ready <= 0) continue; dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); /* Play the packet */ if (dec_frame_len > 0) { alSourceUnqueueBuffers(source, 1, &buffer); alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); int error = alGetError(); if (error != AL_NO_ERROR) { fprintf(stderr, "Error setting buffer %d\n", error); break; } alSourceQueueBuffers(source, 1, &buffer); if (alGetError() != AL_NO_ERROR) { fprintf(stderr, "Error: could not buffer audio\n"); break; } alGetSourcei(source, AL_SOURCE_STATE, &ready); if (ready != AL_PLAYING) alSourcePlay(source); } usleep(1000); } ending: /* clean up codecs */ //pthread_mutex_lock(&cs->ctrl_mutex); /* alDeleteSources(1, &source); alDeleteBuffers(openal_buffers, buffers); alcMakeContextCurrent(NULL); alcDestroyContext(ctx); alcCloseDevice(dev); */ //pthread_mutex_unlock(&cs->ctrl_mutex); _phone->running_decaud = -1; pthread_exit ( NULL ); }
Sound::SoundManager::SoundManager() : m_pDevice(alcOpenDevice(nullptr)) { if(!m_pDevice) LogError() << "Could not open audio device"; //m_Enumeration = alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); ALCenum error; error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; m_pContext = alcCreateContext(m_pDevice, NULL); if (!alcMakeContextCurrent(m_pContext)) LogError() << "Could not make current context"; ALfloat listenerOri[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; alListener3f(AL_POSITION, 0, 0, 1.0f); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alListener3f(AL_VELOCITY, 0, 0, 0); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alListenerfv(AL_ORIENTATION, listenerOri); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALuint source; alGenSources((ALuint)1, &source); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSourcef(source, AL_PITCH, 1); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSourcef(source, AL_GAIN, 1); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSource3f(source, AL_POSITION, 0, 0, 0); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSource3f(source, AL_VELOCITY, 0, 0, 0); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alSourcei(source, AL_LOOPING, AL_FALSE); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALuint buffer; alGenBuffers((ALuint)1, &buffer); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALsizei size, freq; ALenum format; ALvoid *data; ALboolean loop = AL_FALSE; alutLoadWAVFile(reinterpret_cast<ALbyte *>(const_cast<char *>("test.wav")), &format, &data, &size, &freq, &loop); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; alBufferData(buffer, format, data, size, freq); alSourcei(source, AL_BUFFER, buffer);alSourcePlay(source); alSourcePlay(source); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; ALint source_state; alGetSourcei(source, AL_SOURCE_STATE, &source_state); LogInfo() << "Play sound..."; while (source_state == AL_PLAYING) { alGetSourcei(source, AL_SOURCE_STATE, &source_state); error = alGetError(); if (error != AL_NO_ERROR) LogError() << error; LogInfo() << "Play sound..."; } // cleanup context alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); m_pDevice = alcGetContextsDevice(m_pContext); alcMakeContextCurrent(NULL); alcDestroyContext(m_pContext); }
// TODO: generate buffers separately DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels) { if (size[type] <= selection || selection < 0) return de_InvalidSelection; if (channels != 1 && channels != 2) return de_UnsupportedMode; lock; const uint32_t frame_size = (sample_rate * frame_duration / 1000); uint32_t i; for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; ++i); if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; } else *device_idx = i; for (i = 0; i < MAX_DEVICES; i ++) { /* Check if any device has the same selection */ if ( running[type][i] && running[type][i]->selection == selection ) { // printf("a%d-%d:%p ", selection, i, running[type][i]->dhndl); running[type][*device_idx] = running[type][i]; running[type][i]->ref_count ++; unlock; return de_None; } } Device* device = running[type][*device_idx] = calloc(1, sizeof(Device)); device->selection = selection; device->sample_rate = sample_rate; device->frame_duration = frame_duration; device->sound_mode = channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; if (pthread_mutex_init(device->mutex, NULL) != 0) { free(device); unlock; return de_InternalError; } if (type == input) { device->dhndl = alcCaptureOpenDevice(devices_names[type][selection], sample_rate, device->sound_mode, frame_size * 2); #ifdef AUDIO device->VAD_treshold = user_settings->VAD_treshold; #endif } else { device->dhndl = alcOpenDevice(devices_names[type][selection]); if ( !device->dhndl ) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } device->ctx = alcCreateContext(device->dhndl, NULL); alcMakeContextCurrent(device->ctx); alGenBuffers(OPENAL_BUFS, device->buffers); alGenSources((uint32_t)1, &device->source); alSourcei(device->source, AL_LOOPING, AL_FALSE); uint16_t zeros[frame_size]; memset(zeros, 0, frame_size*2); for ( i = 0; i < OPENAL_BUFS; ++i ) { alBufferData(device->buffers[i], device->sound_mode, zeros, frame_size*2, sample_rate); } alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers); alSourcePlay(device->source); } if (alcGetError(device->dhndl) != AL_NO_ERROR) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } if (type == input) { alcCaptureStart(device->dhndl); thread_paused = false; } unlock; return de_None; }
OASound async_init_wav(const char* _file) { OASound sound; memset(&sound,0,sizeof(OASound)); ALvoid* l_DataBuffer = NULL; unsigned int l_FileSize = 0; // OpenAL: first if(x_load_wav(_file, (unsigned char**)&l_DataBuffer , l_FileSize,sound)) // if((l_DataBuffer != NULL) && (l_FileSize > 0)) { if(l_DataBuffer == NULL) { printf("*** DataBuffer NULL!!! *** \n"); } // grab a buffer ID from openAL alGenBuffers(1, (ALuint*)&sound.m_BufferId); ALenum l_error = alGetError(); if(l_error != AL_NO_ERROR) { printf("**** OpenAL ERROR buffer%i\n", l_error); return sound; } else { printf("**** OpenAL OK buffer %i\n", sound.m_BufferId); } ALuint f; if (sound.depth==16) { if (sound.nbchannel == 1) f = AL_FORMAT_MONO16; else f = AL_FORMAT_STEREO16; } else { if (sound.nbchannel == 1) f = AL_FORMAT_MONO8; else f = AL_FORMAT_STEREO8; } alBufferData(sound.m_BufferId, f, l_DataBuffer, l_FileSize, sound.frequency); l_error = alGetError(); if(l_error != AL_NO_ERROR) { printf("**** OpenAL ERROR format\n"); return sound; } // create Source alGenSources(1, (ALuint*)&sound.m_SourceId); l_error = alGetError(); if(l_error != AL_NO_ERROR) { printf("**** OpenAL ERROR source\n"); return sound; } alSourcei(sound.m_SourceId, AL_BUFFER, sound.m_BufferId); l_error = alGetError(); if(l_error != AL_NO_ERROR) { printf("**** OpenAL ERROR source buffer\n"); return sound; } // if loop: //alSourcei(m_SourceId, AL_LOOPING, AL_TRUE); alSourcef(sound.m_SourceId, AL_PITCH, 1.0f); //l_error = alGetError(); //ASSERTC(l_error == AL_NO_ERROR,"**** OpenAL ERROR buffer\n"); //if(l_error != AL_NO_ERROR) //{ // CONSOLEMSG("**** OpenAL ERROR properties\n"); // return FAILURE; //} alSourcef(sound.m_SourceId, AL_GAIN, 1.0f); l_error = alGetError(); if(l_error != AL_NO_ERROR) { printf("**** OpenAL ERROR properties\n"); return sound; } } else { return sound; } if (l_DataBuffer) { free(l_DataBuffer); l_DataBuffer = NULL; } //printf("**** OpenAL Resource load SUCCESS\n"); sound.successfullyLoaded = 1; return sound; }
/** * @brief Initializes the sound subsystem. * * @return 0 on success. */ int sound_al_init (void) { int ret; ALuint s; ALint freq; ALint attribs[4] = { 0, 0, 0, 0 }; /* Default values. */ ret = 0; /* we'll need a mutex */ sound_lock = SDL_CreateMutex(); soundLock(); /* opening the default device */ al_device = alcOpenDevice(NULL); if (al_device == NULL) { WARN(_("Unable to open default sound device")); ret = -1; goto snderr_dev; } /* Query EFX extension. */ if (conf.al_efx) { al_info.efx = alcIsExtensionPresent( al_device, "ALC_EXT_EFX" ); if (al_info.efx == AL_TRUE) { attribs[0] = ALC_MAX_AUXILIARY_SENDS; attribs[1] = 4; } } else al_info.efx = AL_FALSE; /* Create the OpenAL context */ al_context = alcCreateContext( al_device, attribs ); if (al_context == NULL) { WARN(_("Unable to create OpenAL context")); ret = -2; goto snderr_ctx; } /* Clear the errors */ alGetError(); /* Set active context */ if (alcMakeContextCurrent( al_context )==AL_FALSE) { WARN(_("Failure to set default context")); ret = -4; goto snderr_act; } /* Get context information. */ alcGetIntegerv( al_device, ALC_FREQUENCY, sizeof(freq), &freq ); /* Try to enable EFX. */ if (al_info.efx == AL_TRUE) al_enableEFX(); else { al_info.efx_reverb = AL_FALSE; al_info.efx_echo = AL_FALSE; } /* Allocate source for music. */ alGenSources( 1, &music_source ); /* Check for errors. */ al_checkErr(); /* Start allocating the sources - music has already taken his */ source_nstack = 0; source_mstack = 0; while (source_nstack < conf.snd_voices) { if (source_mstack < source_nstack+1) { /* allocate more memory */ if (source_mstack == 0) source_mstack = conf.snd_voices; else source_mstack *= 2; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); } alGenSources( 1, &s ); source_stack[source_nstack] = s; /* How OpenAL distance model works: * * Clamped: * gain = distance_function( CLAMP( AL_REFERENCE_DISTANCE, AL_MAX_DISTANCE, distance ) ); * * Distance functions: * AL_REFERENCE_DISTANCE * * Inverse = ------------------------------------------------------------------------------ * AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR ( distance - AL_REFERENCE_DISTANCE ) * * 1 - AL_ROLLOFF_FACTOR ( distance - AL_REFERENCE_DISTANCE ) * * Linear = ---------------------------------------------------------- * AL_MAX_DISTANCE - AL_REFERENCE_DISTANCE * * / distance \ -AL_ROLLOFF_FACTOR * * Exponential = | --------------------- | * \ AL_REFERENCE_DISTANCE / * * * Some values: * * model falloff reference 100 1000 5000 10000 * linear 1 500 1.000 0.947 0.526 0.000 * inverse 1 500 1.000 0.500 0.100 0.050 * exponent 1 500 1.000 0.500 0.100 0.050 * inverse 0.5 500 1.000 0.667 0.182 0.095 * exponent 0.5 500 1.000 0.707 0.316 0.223 * inverse 2 500 1.000 0.333 0.052 0.026 * exponent 2 500 1.000 0.250 0.010 0.003 */ alSourcef( s, AL_REFERENCE_DISTANCE, 500. ); /* Close distance to clamp at (doesn't get louder). */ alSourcef( s, AL_MAX_DISTANCE, 25000. ); /* Max distance to clamp at (doesn't get quieter). */ alSourcef( s, AL_ROLLOFF_FACTOR, 1. ); /* Determines how it drops off. */ /* Set the filter. */ if (al_info.efx == AL_TRUE) alSource3i( s, AL_AUXILIARY_SEND_FILTER, efx_directSlot, 0, AL_FILTER_NULL ); /* Check for error. */ if (alGetError() == AL_NO_ERROR) source_nstack++; else break; } /* Reduce ram usage. */ source_mstack = source_nstack; source_stack = realloc( source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to total stack. */ source_ntotal = source_mstack; source_total = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_total, source_stack, sizeof(ALuint) * source_mstack ); /* Copy allocated sources to all stack. */ source_nall = source_mstack; source_all = malloc( sizeof(ALuint) * source_mstack ); memcpy( source_all, source_stack, sizeof(ALuint) * source_mstack ); /* Set up how sound works. */ alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); /* Clamping is fundamental so it doesn't sound like crap. */ alDopplerFactor( 1. ); sound_al_env( SOUND_ENV_NORMAL, 0. ); /* Check for errors. */ al_checkErr(); /* we can unlock now */ soundUnlock(); /* debug magic */ DEBUG(_("OpenAL started: %d Hz"), freq); DEBUG(_("Renderer: %s"), alGetString(AL_RENDERER)); if (al_info.efx == AL_FALSE) DEBUG(_("Version: %s without EFX"), alGetString(AL_VERSION)); else DEBUG(_("Version: %s with EFX %d.%d"), alGetString(AL_VERSION), al_info.efx_major, al_info.efx_minor); DEBUG(""); return ret; /* * error handling */ snderr_act: alcDestroyContext( al_context ); snderr_ctx: al_context = NULL; alcCloseDevice( al_device ); snderr_dev: al_device = NULL; soundUnlock(); SDL_DestroyMutex( sound_lock ); sound_lock = NULL; return ret; }
void OpenALStream::SoundLoop() { Common::SetCurrentThreadName("Audio thread - openal"); bool surround_capable = SConfig::GetInstance().bDPL2Decoder; bool float32_capable = false; bool fixed32_capable = false; #if defined(__APPLE__) surround_capable = false; #endif u32 ulFrequency = m_mixer->GetSampleRate(); numBuffers = SConfig::GetInstance().iLatency + 2; // OpenAL requires a minimum of two buffers memset(uiBuffers, 0, numBuffers * sizeof(ALuint)); uiSource = 0; if (alIsExtensionPresent("AL_EXT_float32")) float32_capable = true; // As there is no extension to check for 32-bit fixed point support // and we know that only a X-Fi with hardware OpenAL supports it, // we just check if one is being used. if (strstr(alGetString(AL_RENDERER), "X-Fi")) fixed32_capable = true; // Clear error state before querying or else we get false positives. ALenum err = alGetError(); // Generate some AL Buffers for streaming alGenBuffers(numBuffers, (ALuint*)uiBuffers); err = CheckALError("generating buffers"); // Generate a Source to playback the Buffers alGenSources(1, &uiSource); err = CheckALError("generating sources"); // Set the default sound volume as saved in the config file. alSourcef(uiSource, AL_GAIN, fVolume); // TODO: Error handling // ALenum err = alGetError(); unsigned int nextBuffer = 0; unsigned int numBuffersQueued = 0; ALint iState = 0; soundTouch.setChannels(2); soundTouch.setSampleRate(ulFrequency); soundTouch.setTempo(1.0); soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0); soundTouch.setSetting(SETTING_USE_AA_FILTER, 0); soundTouch.setSetting(SETTING_SEQUENCE_MS, 1); soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28); soundTouch.setSetting(SETTING_OVERLAP_MS, 12); while (m_run_thread.IsSet()) { // Block until we have a free buffer int numBuffersProcessed; alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &numBuffersProcessed); if (numBuffers == numBuffersQueued && !numBuffersProcessed) { soundSyncEvent.Wait(); continue; } // Remove the Buffer from the Queue. if (numBuffersProcessed) { ALuint unqueuedBufferIds[OAL_MAX_BUFFERS]; alSourceUnqueueBuffers(uiSource, numBuffersProcessed, unqueuedBufferIds); err = CheckALError("unqueuing buffers"); numBuffersQueued -= numBuffersProcessed; } // num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD. const u32 stereo_16_bit_size = 4; const u32 dma_length = 32; const u64 ais_samples_per_second = 48000 * stereo_16_bit_size; u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length); u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); unsigned int numSamples = (unsigned int)num_samples_to_render; unsigned int minSamples = surround_capable ? 240 : 0; // DPL2 accepts 240 samples minimum (FWRDURATION) numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; numSamples = m_mixer->Mix(realtimeBuffer, numSamples, false); // Convert the samples from short to float float dest[OAL_MAX_SAMPLES * STEREO_CHANNELS]; for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i) dest[i] = (float)realtimeBuffer[i] / (1 << 15); soundTouch.putSamples(dest, numSamples); double rate = (double)m_mixer->GetCurrentSpeed(); if (rate <= 0) { Core::RequestRefreshInfo(); rate = (double)m_mixer->GetCurrentSpeed(); } // Place a lower limit of 10% speed. When a game boots up, there will be // many silence samples. These do not need to be timestretched. if (rate > 0.10) { soundTouch.setTempo(rate); if (rate > 10) { soundTouch.clear(); } } unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers); if (nSamples <= minSamples) continue; if (surround_capable) { float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS]; DPL2Decode(sampleBuffer, nSamples, dpl2); // zero-out the subwoofer channel - DPL2Decode generates a pretty // good 5.0 but not a good 5.1 output. Sadly there is not a 5.0 // AL_FORMAT_50CHN32 to make this super-explicit. // DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR for (u32 i = 0; i < nSamples; ++i) { dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f; } if (float32_capable) { alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2, nSamples * FRAME_SURROUND_FLOAT, ulFrequency); } else if (fixed32_capable) { int surround_int32[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i) { // For some reason the ffdshow's DPL2 decoder outputs samples bigger than 1. // Most are close to 2.5 and some go up to 8. Hard clamping here, we need to // fix the decoder or implement a limiter. dpl2[i] = dpl2[i] * (INT64_C(1) << 31); if (dpl2[i] > INT_MAX) surround_int32[i] = INT_MAX; else if (dpl2[i] < INT_MIN) surround_int32[i] = INT_MIN; else surround_int32[i] = (int)dpl2[i]; } alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, surround_int32, nSamples * FRAME_SURROUND_INT32, ulFrequency); } else { short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i) { dpl2[i] = dpl2[i] * (1 << 15); if (dpl2[i] > SHRT_MAX) surround_short[i] = SHRT_MAX; else if (dpl2[i] < SHRT_MIN) surround_short[i] = SHRT_MIN; else surround_short[i] = (int)dpl2[i]; } alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short, nSamples * FRAME_SURROUND_SHORT, ulFrequency); } err = CheckALError("buffering data"); if (err == AL_INVALID_ENUM) { // 5.1 is not supported by the host, fallback to stereo WARN_LOG(AUDIO, "Unable to set 5.1 surround mode. Updating OpenAL Soft might fix this issue."); surround_capable = false; } } else { if (float32_capable) { alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer, nSamples * FRAME_STEREO_FLOAT, ulFrequency); err = CheckALError("buffering float32 data"); if (err == AL_INVALID_ENUM) { float32_capable = false; } } else if (fixed32_capable) { // Clamping is not necessary here, samples are always between (-1,1) int stereo_int32[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i) stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31)); alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO32, stereo_int32, nSamples * FRAME_STEREO_INT32, ulFrequency); } else { // Convert the samples from float to short short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS]; for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i) stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15)); alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO16, stereo, nSamples * FRAME_STEREO_SHORT, ulFrequency); } } alSourceQueueBuffers(uiSource, 1, &uiBuffers[nextBuffer]); err = CheckALError("queuing buffers"); numBuffersQueued++; nextBuffer = (nextBuffer + 1) % numBuffers; alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); if (iState != AL_PLAYING) { // Buffer underrun occurred, resume playback alSourcePlay(uiSource); err = CheckALError("occurred resuming playback"); } } }
bool AudioEngine::SingletonInitialize() { if(!AUDIO_ENABLE) return true; const ALCchar *best_device = 0; // Will store the name of the 'best' device for audio playback ALCint highest_version = 0; // The highest version number found CheckALError(); // Clears errors CheckALCError(); // Clears errors // Find the highest-version device available, if the extension for device enumeration is present if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) { const ALCchar *device_list = 0; device_list = alcGetString(0, ALC_DEVICE_SPECIFIER); // Get list of all devices (terminated with two '0') if(CheckALCError() == true) { IF_PRINT_WARNING(AUDIO_DEBUG) << "failed to retrieve the list of available audio devices: " << CreateALCErrorString() << std::endl; } while(*device_list != 0) { // Check all the detected devices ALCint major_v = 0, minor_v = 0; // Open a temporary device for reading in its version number ALCdevice *temp_device = alcOpenDevice(device_list); if(CheckALCError() || temp_device == NULL) { // If we couldn't open the device, just move on to the next IF_PRINT_WARNING(AUDIO_DEBUG) << "couldn't open device for version checking: " << device_list << std::endl; device_list += strlen(device_list) + 1; continue; } // Create a temporary context for the device ALCcontext *temp_context = alcCreateContext(temp_device, 0); if(CheckALCError() || temp_context == NULL) { // If we couldn't create the context, move on to the next device IF_PRINT_WARNING(AUDIO_DEBUG) << "couldn't create a temporary context for device: " << device_list << std::endl; alcCloseDevice(temp_device); device_list += strlen(device_list) + 1; continue; } // Retrieve the version number for the device alcMakeContextCurrent(temp_context); alcGetIntegerv(temp_device, ALC_MAJOR_VERSION, sizeof(ALCint), &major_v); alcGetIntegerv(temp_device, ALC_MINOR_VERSION, sizeof(ALCint), &minor_v); alcMakeContextCurrent(0); // Disable the temporary context alcDestroyContext(temp_context); // Destroy the temporary context alcCloseDevice(temp_device); // Close the temporary device // Check if a higher version device was found if(highest_version < (major_v * 10 + minor_v)) { highest_version = (major_v * 10 + minor_v); best_device = device_list; } device_list += strlen(device_list) + 1; // Go to the next device name in the list } // while (*device_name != 0) } // if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) // Open the 'best' device we found above. If no devices were previously found, // it will try opening the default device (= 0) _device = alcOpenDevice(best_device); if(CheckALCError() || _device == NULL) { PRINT_ERROR << "failed to open an OpenAL audio device: " << CreateALCErrorString() << std::endl; return false; } // Create an OpenAL context _context = alcCreateContext(_device, NULL); if(CheckALCError() || _context == NULL) { PRINT_ERROR << "failed to create an OpenAL context: " << CreateALCErrorString() << std::endl; alcCloseDevice(_device); return false; } alcMakeContextCurrent(_context); CheckALError(); // Clear errors CheckALCError(); // Clear errors // Create as many sources as possible (we fix an upper bound of MAX_DEFAULT_AUDIO_SOURCES) ALuint source; for(uint16 i = 0; i < _max_sources; ++i) { alGenSources(1, &source); if(CheckALError() == true) { _max_sources = i; _max_cache_size = i / 4; break; } _audio_sources.push_back(new private_audio::AudioSource(source)); } if(_max_sources == 0) { PRINT_ERROR << "failed to create at least one OpenAL audio source" << std::endl; return false; } return true; } // bool AudioEngine::SingletonInitialize()
void AudioWorld::initializeMusic() { std::string datPath = "/_work/data/Scripts/_compiled/MUSIC.DAT"; std::string datFile = Utils::getCaseSensitivePath(datPath, m_Engine.getEngineArgs().gameBaseDirectory); if (!Utils::fileExists(datFile)) { LogError() << "Failed to find MUSIC.DAT at: " << datFile; return; } m_MusicVM = new Daedalus::DaedalusVM(datFile); Daedalus::registerGothicEngineClasses(*m_MusicVM); m_MusicVM->getDATFile().iterateSymbolsOfClass("C_MUSICTHEME", [&](size_t i, Daedalus::PARSymbol& s) { Daedalus::GameState::MusicThemeHandle h = m_MusicVM->getGameState().createMusicTheme(); Daedalus::GEngineClasses::C_MusicTheme& mt = m_MusicVM->getGameState().getMusicTheme(h); m_MusicVM->initializeInstance(ZMemory::toBigHandle(h), i, Daedalus::IC_MusicTheme); m_musicThemeSegments[s.name] = mt.file; }); // DirectMusic initialization std::string baseDir = m_Engine.getEngineArgs().gameBaseDirectory; std::string musicPath = Utils::getCaseSensitivePath("/_work/data/Music", baseDir); try { const auto sfFactory = DirectMusic::DlsPlayer::createFactory(); m_musicContext = std::make_unique<DirectMusic::PlayingContext>(44100, 2, sfFactory); auto loader = [musicPath, baseDir](const std::string& name) { const auto search = Utils::lowered(Utils::stripFilePath(name)); for (const auto& file : Utils::getFilesInDirectory(musicPath)) { const auto lowercaseName = Utils::lowered(Utils::stripFilePath(file)); if (lowercaseName == search) { return Utils::readBinaryFileContents(file); } } return std::vector<std::uint8_t>(); }; m_musicContext->provideLoader(loader); for (const auto& segment : Utils::getFilesInDirectory(musicPath, "sgt")) { const auto lowercaseName = Utils::lowered(Utils::stripFilePath(segment)); const auto segm = m_musicContext->loadSegment(segment); LogInfo() << "Loading " + segment; m_Segments[lowercaseName] = m_musicContext->prepareSegment(*segm); } LogInfo() << "All segments loaded."; alGenBuffers(RE_NUM_MUSIC_BUFFERS, m_musicBuffers); alGenSources(1, &m_musicSource); // Set the default volume alSourcef(m_musicSource, AL_GAIN, 1); // Set the default position of the sound alSource3f(m_musicSource, AL_POSITION, 0, 0, 0); m_musicRenderThread = std::thread(&AudioWorld::musicRenderFunction, this); } catch (const std::exception& exc) { LogError() << "Couldn't initialize music system: " << exc.what(); } }
int main(int argc, char **argv) { ALboolean enumeration; const ALCchar *devices; const ALCchar *defaultDeviceName = argv[1]; int ret; #ifdef LIBAUDIO WaveInfo *wave; #endif char *bufferData; ALCdevice *device; ALvoid *data; ALCcontext *context; ALsizei size, freq; ALenum format; ALuint buffer, source; ALfloat listenerOri[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }; ALboolean loop = AL_FALSE; ALCenum error; ALint source_state; enumeration = alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); if (enumeration == AL_FALSE) fprintf(stderr, "enumeration extension not available\n"); list_audio_devices(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); if (!defaultDeviceName) defaultDeviceName = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); device = alcOpenDevice(defaultDeviceName); if (!device) { fprintf(stderr, "unable to open default device\n"); return -1; } fprintf(stdout, "Device: %s\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); alGetError(); context = alcCreateContext(device, NULL); if (!alcMakeContextCurrent(context)) { fprintf(stderr, "failed to make default context\n"); return -1; } TEST_ERROR("make default context"); /* set orientation */ alListener3f(AL_POSITION, 0, 0, 1.0f); TEST_ERROR("listener position"); alListener3f(AL_VELOCITY, 0, 0, 0); TEST_ERROR("listener velocity"); alListenerfv(AL_ORIENTATION, listenerOri); TEST_ERROR("listener orientation"); alGenSources((ALuint)1, &source); TEST_ERROR("source generation"); alSourcef(source, AL_PITCH, 1); TEST_ERROR("source pitch"); alSourcef(source, AL_GAIN, 1); TEST_ERROR("source gain"); alSource3f(source, AL_POSITION, 0, 0, 0); TEST_ERROR("source position"); alSource3f(source, AL_VELOCITY, 0, 0, 0); TEST_ERROR("source velocity"); alSourcei(source, AL_LOOPING, AL_FALSE); TEST_ERROR("source looping"); alGenBuffers(1, &buffer); TEST_ERROR("buffer generation"); #ifdef LIBAUDIO /* load data */ wave = WaveOpenFileForReading("test.wav"); if (!wave) { fprintf(stderr, "failed to read wave file\n"); return -1; } ret = WaveSeekFile(0, wave); if (ret) { fprintf(stderr, "failed to seek wave file\n"); return -1; } bufferData = malloc(wave->dataSize); if (!bufferData) { perror("malloc"); return -1; } ret = WaveReadFile(bufferData, wave->dataSize, wave); if (ret != wave->dataSize) { fprintf(stderr, "short read: %d, want: %d\n", ret, wave->dataSize); return -1; } alBufferData(buffer, to_al_format(wave->channels, wave->bitsPerSample), bufferData, wave->dataSize, wave->sampleRate); TEST_ERROR("failed to load buffer data"); #else alutLoadWAVFile("test.wav", &format, &data, &size, &freq, &loop); TEST_ERROR("loading wav file"); alBufferData(buffer, format, data, size, freq); TEST_ERROR("buffer copy"); #endif alSourcei(source, AL_BUFFER, buffer); TEST_ERROR("buffer binding"); alSourcePlay(source); TEST_ERROR("source playing"); alGetSourcei(source, AL_SOURCE_STATE, &source_state); TEST_ERROR("source state get"); while (source_state == AL_PLAYING) { alGetSourcei(source, AL_SOURCE_STATE, &source_state); TEST_ERROR("source state get"); } /* exit context */ alDeleteSources(1, &source); alDeleteBuffers(1, &buffer); device = alcGetContextsDevice(context); alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); return 0; }