www.pudn.com > ncdzsrc.rar > streams.c
/***************************************************************************
stream.c
サウンドストリーム処理
***************************************************************************/
#include "neogeocd.h"
#define MAX_CHANNLES 2
#define BUFFER_LEN 16384
/****************************************************************************
ローカル変数
***************************************************************************/
static INT16 stream_buffer[MAX_CHANNLES][BUFFER_LEN];
static int stream_buffer_pos;
static int stream_sample_length;
static void (*stream_callback)(INT16 **buffer, int length);
static INT16 mixing_buffer[BUFFER_LEN];
static int samples_this_frame;
static double volume;
/***************************************************************************
グローバル関数
***************************************************************************/
/*------------------------------------------------------
サウンドストリーム開始
引 数: なし
戻り値: 0:成功 1:失敗
-----------------------------------------------------*/
int streams_sh_start(void)
{
memset(mixing_buffer, 0, BUFFER_LEN * sizeof(INT16));
memset(stream_buffer, 0, BUFFER_LEN * sizeof(INT16) * MAX_CHANNLES);
volume = 0;
if (sample_rate == 0)
return 0;
samples_this_frame = osd_start_audio_stream();
if (samples_this_frame)
{
stream_set_volume();
return 0;
}
sample_rate = 0;
return 1;
}
/*------------------------------------------------------
サウンドストリーム停止
引 数: なし
戻り値: なし
-----------------------------------------------------*/
void streams_sh_stop(void)
{
if (sample_rate)
osd_stop_audio_stream();
}
/*------------------------------------------------------
ストリームの音量反映
引 数: INT16 val データの値
戻り値: なし
-----------------------------------------------------*/
INLINE INT16 apply_volume(INT16 val)
{
INT32 value = (INT32)val * volume;
if (value > 32767) return 32767;
if (value < -32768) return -32768;
return (INT16)value;
}
/*------------------------------------------------------
サウンドストリームの更新
引 数: なし
戻り値: なし
-----------------------------------------------------*/
void streams_sh_update(void)
{
if (sample_rate)
{
int i, buflen;
INT16 *buf[MAX_CHANNLES];
buflen = samples_this_frame - stream_buffer_pos;
if (buflen > 0)
{
for (i = 0; i < MAX_CHANNLES; i++)
buf[i] = stream_buffer[i] + stream_buffer_pos;
(*stream_callback)(buf, buflen);
}
stream_buffer_pos = 0;
for (i = 0; i < samples_this_frame; i++)
{
mixing_buffer[i * 2 + 0] = stream_buffer[0][i];
mixing_buffer[i * 2 + 1] = stream_buffer[1][i];
stream_buffer[0][i] = stream_buffer[1][i] = 0;
}
if (volume != 1.0)
{
for (i = 0; i < samples_this_frame * 2; i++)
mixing_buffer[i] = apply_volume(mixing_buffer[i]);
}
samples_this_frame = osd_update_audio_stream(mixing_buffer);
}
}
/*------------------------------------------------------
ストリームの初期化
引 数: void (*callbaxk)(...) コールバック関数
int length ストリームのサイズ
戻り値: 1:成功 0:サウンド未使用
-----------------------------------------------------*/
int stream_init(void (*callback)(INT16 **buffer, int length))
{
if (sample_rate)
{
stream_buffer_pos = 0;
stream_sample_length = 1000000 / sample_rate;
stream_callback = callback;
return 1;
}
return 0;
}
/*------------------------------------------------------
ストリームの更新
引 数: int min_interval 更新間隔の最小値(μ秒)
戻り値: なし
-----------------------------------------------------*/
void stream_update(int min_interval)
{
if (sample_rate)
{
int i, buflen;
INT16 *buf[MAX_CHANNLES];
buflen = sound_scalebufferpos(samples_this_frame) - stream_buffer_pos;
if (buflen * stream_sample_length > min_interval)
{
for (i = 0; i < MAX_CHANNLES; i++)
buf[i] = stream_buffer[i] + stream_buffer_pos;
(*stream_callback)(buf, buflen);
stream_buffer_pos += buflen;
}
}
}
/*------------------------------------------------------
サウンドストリームの音量設定
引 数: なし
戻り値: なし
-----------------------------------------------------*/
void stream_set_volume(void)
{
volume = (double)options.sound_volume / 100.0;
}