ALuint
SoundManager::load_file_into_buffer(const std::string& filename)
{
  // open sound file
  std::auto_ptr<SoundFile> file (load_sound_file(filename));
  
  ALenum format = get_sample_format(file.get());
  ALuint buffer;
  alGenBuffers(1, &buffer);
  check_al_error("Couldn't create audio buffer: ");
  char* samples = new char[file->size];
  try {
    file->read(samples, file->size);
    alBufferData(buffer, format, samples,
        static_cast<ALsizei> (file->size),
        static_cast<ALsizei> (file->rate));
    check_al_error("Couldn't fill audio buffer: ");
  } catch(...) {
    delete[] samples;
    throw;
  }
  delete[] samples;

  return buffer;
}
예제 #2
0
void fs_emu_init_audio_stream(int stream,
        fs_emu_audio_stream_options *options) {
    fs_log("initializing audio stream %d\n", stream);
    audio_stream *s = g_malloc0(sizeof(audio_stream));
    s->buffer_size = options->buffer_size;
    s->frequency = options->frequency;
    s->num_buffers = MAX_BUFFERS;
    s->min_buffers = options->min_buffers;
    fs_log("frequency: %d, buffers: %d buffer size: %d bytes\n",
            s->frequency, s->num_buffers, s->buffer_size);
    s->mutex = g_mutex_new();
    s->queue = g_queue_new();
    alGenSources(1, &s->source);
    check_al_error("alGenSources");
    for (int i = 0; i < s->num_buffers; i++) {
        ALuint buffer;
        alGenBuffers(1, &buffer);
        check_al_error("alGenBuffers");
        g_queue_push_tail(s->queue, GUINT_TO_POINTER(buffer));
    }
    s->buffers_queued = 0;

    // FIXME: configure elsewhere
    if (stream == 0) {
        s->fill_target = 8 * 1024;
    }
    else {
        s->fill_target = 0;
    }
    s->pid_last_error = 0;
    s->pid_last_last_error = 0;
    s->pid_last_time = 0;
    s->pid_last_last_time = 0;
    g_streams[stream] = s;
}
예제 #3
0
static void unqueue_old_buffers(int stream)
{
    audio_stream *s = g_streams[stream];
    ALint old_buffers = 0;
    fs_mutex_lock(s->mutex);
    // locking here because unqueue_old_buffers can be run called from
    // both the video thread and the emulation thread (consider changing this,
    // perhaps even have a separate thread for periodically unqueuing).
    alGetSourcei(s->source, AL_BUFFERS_PROCESSED, &old_buffers);
    check_al_error("alGetSourcei (AL_BUFFERS_PROCESSED)");

    if (old_buffers > 0) {
        ALuint buffers[MAX_BUFFERS];
        old_buffers = MIN(old_buffers, MAX_BUFFERS);
        alSourceUnqueueBuffers(s->source, old_buffers, buffers);
        if (check_al_error("alSourceUnqueueBuffers") != AL_NO_ERROR) {
            fs_log("while trying to unqueue %d buffers\n");
        }
        for (int i = 0; i < old_buffers; i++) {
            g_queue_push_tail(s->queue, FS_UINT_TO_POINTER(buffers[i]));
        }
        s->buffers_queued -= old_buffers;
    }
    fs_mutex_unlock(s->mutex);
}
예제 #4
0
 void loop(const OpenAlSound& sound) {
     alSourcei(_source, AL_LOOPING, AL_TRUE);
     check_al_error("alSourcei");
     alSourcei(_source, AL_BUFFER, sound.buffer());
     check_al_error("alSourcei");
     alSourcePlay(_source);
     check_al_error("alSourcePlay");
 }
예제 #5
0
 OpenAlChannel(OpenAlSoundDriver& driver):
         _driver(driver) {
     alGenSources(1, &_source);
     check_al_error("alGenSources");
     alSourcef(_source, AL_PITCH, 1.0f);
     alSourcef(_source, AL_GAIN, 1.0f);
     check_al_error("alSourcef");
 }
예제 #6
0
파일: sound.cpp 프로젝트: proydakov/cppzone
system::sound_id system::load_wav(const std::string& filename)
{
    sound_id bad_id = -1;
    
    sound_info  buffer;
    
    ALenum    format;
    ALvoid*   data;
    ALsizei   size;
    ALsizei   freq;
    ALboolean loop;
    ALuint    buf_id = 0;
    
    buffer.m_filename = filename;
    sound_buffers::const_iterator end_it = m_d->m_buffers->end();
    for(sound_buffers::const_iterator it = m_d->m_buffers->begin(); it != end_it; ++it) {
        if(it->second.m_filename == filename) {
            buf_id = it->first;
            break;
        }
    }
    
    if(!buf_id) {
        alGenBuffers(1, &buffer.m_id);
        if(!check_al_error()) {
            return false;
        }
        alutLoadWAVFile((ALbyte *)filename.c_str(), &format, &data, &size, &freq, &loop);
        if (!check_al_error()) {
            return bad_id;
        }
        
        buffer.m_format = format;
        buffer.m_rate   = freq;
        
        alBufferData(buffer.m_id, format, data, size, freq);
        if (!check_al_error()) {
            return bad_id;
        }
        
        alutUnloadWAV(format, data, size, freq);
        if (!check_al_error()) {
            return bad_id;
        }
        m_d->m_buffers->insert(sound_buffers::value_type(buf_id, buffer));
    }
    else {
        buffer = (*m_d->m_buffers)[buf_id];
    }
    
    return buffer.m_id;
}
예제 #7
0
int fs_emu_queue_audio_buffer(int stream, int16_t* data, int size) {
	if (g_fs_emu_benchmarking) {
		// no audio output while benchmarking
		return 0;
	}
    //fs_log("fs_emu_queue_audio_buffer stream %d\n", stream);
    audio_stream *s = g_streams[stream];

    ALuint buffer = 0;
    g_mutex_lock(s->mutex);
    //while (1) {
    buffer = GPOINTER_TO_UINT(g_queue_pop_head(s->queue));
    if (!buffer) {
        fs_log("no audio buffer available - dropping data\n");
        g_mutex_unlock(s->mutex);
        return 0;
    }
    s->buffers_queued += 1;
    // create a local copy while we have the lock
    int buffers_queued = s->buffers_queued;
    g_mutex_unlock(s->mutex);

    alBufferData(buffer, AL_FORMAT_STEREO16, data, size, s->frequency);
    check_al_error("alBufferData");
    alSourceQueueBuffers(s->source, 1, &buffer);
    check_al_error("alSourceQueueBuffers");

    ALint state;
    alGetSourcei(s->source, AL_SOURCE_STATE, &state);
    check_al_error("alGetSourcei (AL_SOURCE_STATE)");
    if (state != AL_PLAYING) {
        // we have had a buffer underrun - we now wait until we have queued
        // some buffers
        if (buffers_queued < s->min_buffers) {
            // want more buffers
        }
        else {
            fs_log("restarting audio stream %d (buffer underrun)\n", stream);
            alSourcePlay(s->source);
            check_al_error("alSourcePlay");
        }
    }

	double want_volume = g_volume * 0.9;
	if (want_volume != s->source_volume_current) {
		s->source_volume_current = want_volume;
		alSourcef(s->source, AL_GAIN, want_volume);
	}

    unqueue_old_buffers(stream);
    return buffer;
}
SoundManager::SoundManager()
  : device(0), context(0), sound_enabled(false), music_source(0),
    music_enabled(true)
{
  try {
    device = alcOpenDevice(0);
    if(device == 0) {
      print_openal_version();
      throw std::runtime_error("Couldn't open audio device.");
    }

    int attributes[] = { 0 };
    context = alcCreateContext(device, attributes);
    check_alc_error("Couldn't create audio context: ");
    alcMakeContextCurrent(context);
    check_alc_error("Couldn't select audio context: ");

    check_al_error("Audio error after init: ");
    sound_enabled = true;
  } catch(std::exception& e) {
    device = 0;
    context = 0;
    log_warning << "Couldn't initialize audio device:" << e.what() << std::endl;
    print_openal_version();
    throw e;
  }
}
예제 #9
0
static void set_paused(int stream, bool paused)
{
    if (paused) {
        fs_log("fs_emu_audio_resume_stream %d\n", stream);
        audio_stream *s = g_streams[stream];
        alSourcePause(s->source);
        g_fs_emu_audio_stream_playing[stream] = 0;
        check_al_error("alSourcePlay");
    } else {
        fs_log("fs_emu_audio_resume_stream %d\n", stream);
        audio_stream *s = g_streams[stream];
        alSourcePlay(s->source);
        g_fs_emu_audio_stream_playing[stream] = 1;
        check_al_error("alSourcePlay");
    }
}
예제 #10
0
ALuint
SoundManager::load_file_into_buffer(SoundFile& file)
{
  ALenum format = get_sample_format(file);
  ALuint buffer;
  alGenBuffers(1, &buffer);
  check_al_error("Couldn't create audio buffer: ");
  std::unique_ptr<char[]> samples(new char[file.size]);
  file.read(samples.get(), file.size);
  alBufferData(buffer, format, samples.get(),
               static_cast<ALsizei>(file.size),
               static_cast<ALsizei>(file.rate));
  check_al_error("Couldn't fill audio buffer: ");

  return buffer;
}
예제 #11
0
 void buffer(const AudioFile& audio_file) {
     Bytes data;
     ALenum format;
     ALsizei frequency;
     audio_file.convert(&data, &format, &frequency);
     alBufferData(_buffer, format, data.data(), data.size(), frequency);
     check_al_error("alBufferData");
 }
예제 #12
0
static void fs_emu_init_audio_stream(int stream,
                              fs_emu_audio_stream_options *options)
{
    audio_stream *s = g_malloc0(sizeof(audio_stream));
    s->buffer_size = options->buffer_size;
    s->frequency = options->frequency;
    s->num_buffers = MAX_BUFFERS;
    s->min_buffers = options->min_buffers;
    fs_log("AUDIO: Stream %d,  frequency: %d, buffers: %d buffer "
           "size: %d bytes\n", stream, s->frequency, s->num_buffers,
           s->buffer_size);
    s->mutex = fs_mutex_create();
    s->queue = g_queue_new();
    s->source_volume_current = 1.0;
    s->buffers_queued = 0;
    s->pid_last_error = 0;
    s->pid_last_last_error = 0;
    s->pid_last_time = 0;
    s->pid_last_last_time = 0;

    alGenSources(1, &s->source);
    //alSourcei (s->source, AL_SOURCE_RELATIVE, AL_TRUE);
    //alSource3f(s->source, AL_POSITION, 0.0, 0.0, -1.0);
    //alSourcef (s->source, AL_ROLLOFF_FACTOR, 0.0);
    // AL_DIRECT_CHANNELS_SOFT
    alSourcei(s->source, 0x1033, AL_TRUE);

    check_al_error("alGenSources");
    for (int i = 0; i < s->num_buffers; i++) {
        ALuint buffer;
        alGenBuffers(1, &buffer);
        check_al_error("alGenBuffers");
        g_queue_push_tail(s->queue, FS_UINT_TO_POINTER(buffer));
    }

    if (stream == 0) {
        s->fill_target = g_default_fill_target;
    } else {
        s->fill_target = 0;
    }

    g_streams[stream] = s;
}
ALuint
SoundManager::load_file_into_buffer(SoundFile* file)
{
  ALenum format = get_sample_format(file);
  ALuint buffer;
  alGenBuffers(1, &buffer);
  check_al_error("Couldn't create audio buffer: ");
  char* samples = new char[file->size];
  try {
    file->read(samples, file->size);
    alBufferData(buffer, format, samples,
        static_cast<ALsizei> (file->size),
        static_cast<ALsizei> (file->rate));
    check_al_error("Couldn't fill audio buffer: ");
  } catch(...) {
    delete[] samples;
    throw;
  }
  delete[] samples;

  return buffer;
}
예제 #14
0
static void pid_controller_step(int stream, int time_ms)
{
    audio_stream *s = g_streams[stream];
    if (s->fill_target == 0) {
        return;
    }
    if (s->pid_last_last_time == 0) {
        s->pid_last_time = time_ms;
        s->pid_last_last_time = time_ms;
    }
    int dt = time_ms - s->pid_last_last_time;
    int error = s->fill_target - s->fill_stat_buffer_avg;

    //static double last_error = 0.0;
    //if (s->pid_last_error == 0.0) {
    //    s->pid_last_error = error;
    //}
    //s->pid_integral = s->pid_integral + (error * dt);
    //s->pid_integral = s->err_stat_buffer_sum;

    double derivative;
    if (dt > 0) {
        derivative = (s->pid_last_last_error - error) / dt;
    } else {
        derivative = 0;
    }
    double output = KP * error + KI * s->err_stat_buffer_sum + KD * derivative;

    s->pid_last_last_error = s->pid_last_error;
    s->pid_last_last_time = s->pid_last_time;
    s->pid_last_error = error;
    s->pid_last_time = time_ms;

    s->pitch = g_default_audio_pitch - output;
    s->pitch = MAX(0.5, MIN(2.0, s->pitch));
#if 0
    static int count = 0;
    if (++count % 25 == 0) {
        printf("pitch: %0.3f (output %0.6f err %d err sum %d)\n",
               s->pitch, output, error, s->err_stat_buffer_sum);
    }
#endif
    alSourcef(s->source, AL_PITCH, (ALfloat) s->pitch);
    check_al_error("alSourcef (AL_PITCH)");
}
예제 #15
0
void fs_emu_audio_init() {
    fs_log("fs_emu_audio_init\n");

    // select the "preferred device"
    g_device = alcOpenDevice(NULL);
    if (!g_device) {
        fs_log("WARNING: could not open OpenAL device\n");
    }

#if 0
    // FIXME: enable later
    ALCint attributes[3] = { ALC_FREQUENCY,  48000, 0 };

    fs_log("openal: trying 48000\n");
    g_context = alcCreateContext(g_device, attributes);
    if (g_context) {
        g_audio_out_frequency = 48000;
    }
    else {
        //check_al_error("alcCreateContext");
        fs_log("openal: trying without frequency specified\n");
   }
#endif

    if (!g_context) {
        g_context = alcCreateContext(g_device, NULL);
        g_audio_out_frequency = 44100;
    }

    if (g_context) {
        fs_log("openal: created context\n");
        alcMakeContextCurrent(g_context);
        check_al_error("alcMakeContextCurrent");
        fs_log("openal: made context current\n");
    }
    else {
        fs_log("ERROR: no OpenAL context\n");
        //check_al_error("alcCreateContext");
    }
    // FIXME:
}
예제 #16
0
SoundManager::SoundManager() :
  device(0), 
  context(0), 
  sound_enabled(false), 
  buffers(),
  sources(),
  update_list(),
  music_source(0),
  music_enabled(false),
  current_music()
{
  try {
    device = alcOpenDevice(0);
    if (device == NULL) {
      throw std::runtime_error("Couldn't open audio device.");
    }

    int attributes[] = { 0 };
    context = alcCreateContext(device, attributes);
    check_alc_error("Couldn't create audio context: ");
    alcMakeContextCurrent(context);
    check_alc_error("Couldn't select audio context: ");

    check_al_error("Audio error after init: ");
    sound_enabled = true;
    music_enabled = true;
  } catch(std::exception& e) {
    if(context != NULL) {
      alcDestroyContext(context);
      context = NULL; 
    }
    if(device != NULL) {
      alcCloseDevice(device);
      device = NULL;
    }
    log_warning << "Couldn't initialize audio device: " << e.what() << std::endl;
    print_openal_version();
  }
}
예제 #17
0
void fs_emu_audio_openal_init(void)
{
    fs_log("fs_emu_audio_openal_init\n");
    register_functions();

    // select the "preferred device"
    g_device = alcOpenDevice(NULL);
    if (g_device) {
        fs_log("[OPENAL] Opened device: %s\n",
               alcGetString(g_device, ALC_DEVICE_SPECIFIER));
    } else {
        fs_log("[OPENAL] NULL from alcOpenDevice\n");
        ALenum error_code = alGetError();
        fs_log("[OPENAL] Error code %d\n", error_code);
        if (alGetString(error_code)) {
            fs_log("[OPENAL] %s\n", alGetString(error_code));
        }
        fs_emu_warning("OPENAL: Could not open audio device");
    }
    if (!g_device) {
        return;
    }
    log_openal_info();
    log_openal_devices();

    int frequencies[] = { 48000, 44100, 0 };
    if (fs_config_get_int("audio_frequency") != FS_CONFIG_NONE) {
        frequencies[0] = fs_config_get_int("audio_frequency");
    }

    for (int i = 0; frequencies[i]; i++) {
        int frequency = frequencies[i];
        fs_log("OPENAL: trying frequency %d\n", frequency);
        ALCint attributes[] = {
            ALC_MONO_SOURCES, 0,
            ALC_STEREO_SOURCES, 2,
            ALC_FREQUENCY, frequency,
            0
        };

        g_context = alcCreateContext(g_device, attributes);
        if (g_context) {
            g_audio_out_frequency = frequency;
            break;
        }
    }

    if (g_context) {
        fs_log("OPENAL: created context\n");
        alcMakeContextCurrent(g_context);
        check_al_error("alcMakeContextCurrent");
        fs_log("OPENAL: made context current\n");
    } else {
        fs_emu_warning("OpenAL: no context created\n");
        //check_al_error("alcCreateContext");
    }

    int stereo_sources;
    alcGetIntegerv(g_device, ALC_STEREO_SOURCES, 1, &stereo_sources);
    fs_log("openal: number of stereo sources is %d\n", stereo_sources);

    // FIXME: configure elsewhere
    int abt = fs_config_get_int_clamped("audio_buffer_target_size",
                                        1, 100);
    if (abt == FS_CONFIG_NONE) {
        if (fs_config_get_int("audio_buffer_target_bytes") != FS_CONFIG_NONE) {
            fs_emu_warning("Use audio_buffer_target_size instead\n");
        }
        abt = 40;
#if 0
        if (abt == FS_CONFIG_NONE) {
            abt = 40;
        } else {
            abt = (int) (abt / 1000.0 * (options->frequency * 2 * 2));
        }
#endif
    }
    fs_log("AUDIO: Buffer target size (ms) = %d\n", abt);
    //abt = (int) (abt / 1000.0 * (options->frequency * 2 * 2));
    // fs_log("AUDIO: Buffer target size (bytes) = %d\n", abt);
    /* Specifying fill target in microseconds */
    g_default_fill_target = abt * 1000;
}
예제 #18
0
 static ALuint generate_buffer() {
     ALuint buffer;
     alGenBuffers(1, &buffer);
     check_al_error("alGenBuffers");
     return buffer;
 }
예제 #19
0
static int queue_buffer(int stream, int16_t* data, int size)
{
    if (g_fs_emu_benchmark_mode) {
        /* no audio output while benchmarking */
        return 0;
    }
    if (g_fs_emu_benchmarking) {
        /* no audio output while benchmarking */
        return 0;
    }
    //fs_log("fs_emu_queue_audio_buffer stream %d size %d\n", stream, size);
    audio_stream *s = g_streams[stream];

    ALuint buffer = 0;
    fs_mutex_lock(s->mutex);
    //while (1) {
    buffer = FS_POINTER_TO_UINT(g_queue_pop_head(s->queue));
    if (!buffer) {
        fs_log("no audio buffer available - dropping data\n");
        fs_mutex_unlock(s->mutex);
        return 0;
    }
    s->buffers_queued += 1;
    // create a local copy while we have the lock
    //int buffers_queued = s->buffers_queued;
    fs_mutex_unlock(s->mutex);

#if 0
    /* for debugging, clear one of the stereo channels */
    int16_t *d = data;
    for (int i = 0; i < size / 4; i++) {
        d++;
        *d = 0;
        d++;
    }
#endif

    alBufferData(buffer, AL_FORMAT_STEREO16, data, size, s->frequency);
    check_al_error("alBufferData");
    alSourceQueueBuffers(s->source, 1, &buffer);
    check_al_error("alSourceQueueBuffers");

    ALint state;
    alGetSourcei(s->source, AL_SOURCE_STATE, &state);
    check_al_error("alGetSourcei (AL_SOURCE_STATE)");
    if (state != AL_PLAYING) {
        g_fs_emu_audio_buffer_underrun_time = fs_get_monotonic_time();
        g_fs_emu_audio_buffer_underruns += 1;
        // we have had a buffer underrun - we now wait until we have queued
        // some buffers
        //if (buffers_queued < s->min_buffers) {
        //    // want more buffers
        //}
        //else {
        fs_log("restarting audio stream %d (buffer underrun)\n", stream);
        alSourcePlay(s->source);
        g_fs_emu_audio_stream_playing[stream] = 1;
        check_al_error("alSourcePlay");
        //}
    }

    double want_volume = g_fs_emu_audio_want_volume[stream] * 0.9;
    if (want_volume != s->source_volume_current) {
        s->source_volume_current = want_volume;
        alSourcef(s->source, AL_GAIN, want_volume);
    }

    unqueue_old_buffers(stream);
    return buffer;
}
예제 #20
0
 virtual void amp(uint8_t volume) {
     alSourcef(_source, AL_GAIN, volume / 256.0f);
     check_al_error("alSourcef");
 }
예제 #21
0
 virtual void quiet() {
     alSourceStop(_source);
     check_al_error("alSourceStop");
 }