/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS sound driver implementation. * * Originally by Peter Wang, rewritten to use the BSoundPlayer * class by Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #ifndef ALLEGRO_BEOS #error something is wrong with the makefile #endif #ifndef SCAN_DEPEND #include #endif #ifdef ALLEGRO_BIG_ENDIAN #define BE_SOUND_ENDIAN B_MEDIA_BIG_ENDIAN #else #define BE_SOUND_ENDIAN B_MEDIA_LITTLE_ENDIAN #endif sem_id _be_sound_stream_lock = -1; static bool be_sound_active = false; static bool be_sound_stream_locked = false; static BLocker *locker = NULL; static BSoundPlayer *be_sound = NULL; static int be_sound_bufsize; static int be_sound_signed; static char be_sound_desc[256] = EMPTY_STRING; /* be_sound_handler: * Update data. */ static void be_sound_handler(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format) { locker->Lock(); acquire_sem(_be_sound_stream_lock); if (be_sound_active) { _mix_some_samples((unsigned long)buffer, 0, be_sound_signed); } else { memset(buffer, 0, size); } release_sem(_be_sound_stream_lock); locker->Unlock(); } /* be_sound_detect. * Return TRUE if sound available. */ extern "C" int be_sound_detect(int input) { BSoundPlayer *sound; media_raw_audio_format format; status_t status; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } format.frame_rate = 11025; format.channel_count = 1; format.format = media_raw_audio_format::B_AUDIO_UCHAR; format.byte_order = BE_SOUND_ENDIAN; format.buffer_size = 0; sound = new BSoundPlayer(&format); status = sound->InitCheck(); delete sound; return (status == B_OK) ? TRUE : FALSE; } /* be_sound_init: * Init sound driver. */ extern "C" int be_sound_init(int input, int voices) { media_raw_audio_format format; char tmp1[128], tmp2[128]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } be_sound_active = false; /* create BPushGameSound instance */ format.frame_rate = (_sound_freq > 0) ? _sound_freq : 44100; format.channel_count = (_sound_stereo) ? 2 : 1; format.format = (_sound_bits == 8) ? (media_raw_audio_format::B_AUDIO_UCHAR) : (media_raw_audio_format::B_AUDIO_SHORT); format.byte_order = BE_SOUND_ENDIAN; format.buffer_size = 0; be_sound = new BSoundPlayer(&format, "Sound player", be_sound_handler); if (be_sound->InitCheck() != B_OK) { goto cleanup; } /* read the sound format back */ format = be_sound->Format(); switch (format.format) { case media_raw_audio_format::B_AUDIO_UCHAR: _sound_bits = 8; be_sound_signed = FALSE; break; case media_raw_audio_format::B_AUDIO_SHORT: _sound_bits = 16; be_sound_signed = TRUE; break; default: goto cleanup; } _sound_stereo = (format.channel_count == 2) ? 1 : 0; _sound_freq = (int)format.frame_rate; /* start internal mixer */ be_sound_bufsize = format.buffer_size; digi_beos.voices = voices; if (_mixer_init(be_sound_bufsize / (_sound_bits / 8), _sound_freq, _sound_stereo, ((_sound_bits == 16) ? 1 : 0), &digi_beos.voices) != 0) { goto cleanup; } /* start audio output */ locker = new BLocker(); if (!locker) goto cleanup; be_sound->Start(); be_sound->SetHasData(true); uszprintf(be_sound_desc, sizeof(be_sound_desc), get_config_text("%d bits, %s, %d bps, %s"), _sound_bits, uconvert_ascii(be_sound_signed ? "signed" : "unsigned", tmp1), _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp2)); digi_driver->desc = be_sound_desc; be_sound_active = true; return 0; cleanup: { be_sound_exit(input); return -1; } } /* be_sound_exit: * Shutdown sound driver. */ extern "C" void be_sound_exit(int input) { if (input) { return; } be_sound_active = false; be_sound->Stop(); acquire_sem(_be_sound_stream_lock); _mixer_exit(); release_sem(_be_sound_stream_lock); delete be_sound; delete locker; be_sound = NULL; locker = NULL; } /* be_sound_lock_voice: * Locks audio stream for exclusive access. */ extern "C" void *be_sound_lock_voice(int voice, int start, int end) { if (!be_sound_stream_locked) { be_sound_stream_locked = true; acquire_sem(_be_sound_stream_lock); } return NULL; } /* be_sound_unlock_voice: * Unlocks audio stream. */ void be_sound_unlock_voice(int voice) { if (be_sound_stream_locked) { be_sound_stream_locked = false; release_sem(_be_sound_stream_lock); } } /* be_sound_buffer_size: * Returns the current buffer size, for use by the audiostream code. */ extern "C" int be_sound_buffer_size() { return be_sound_bufsize / (_sound_bits / 8) / (_sound_stereo ? 2 : 1); } /* be_sound_mixer_volume: * Set mixer volume. */ extern "C" int be_sound_mixer_volume(int volume) { if (!be_sound) return -1; be_sound->SetVolume((float)volume / 255.0); return 0; } /* be_sound_suspend: * Pauses the sound output. */ extern "C" void be_sound_suspend(void) { if (!be_sound) return; locker->Lock(); be_sound_active = false; locker->Unlock(); } /* be_sound_resume: * Resumes the sound output. */ extern "C" void be_sound_resume(void) { if (!be_sound) return; locker->Lock(); be_sound_active = true; locker->Unlock(); }