📄 soundprovider_recorder_oss.cpp
字号:
/* $Id: soundprovider_recorder_oss.cpp,v 1.4 2003/09/22 22:15:13 mbn Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Sound/precomp.h"
#include "API/Sound/soundformat.h"
#include <API/Core/System/error.h>
#include "API/Core/System/cl_assert.h"
#include "API/Core/System/system.h"
#include "API/Core/System/log.h"
#include "soundprovider_recorder_oss.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#ifdef __CYGWIN__
#include <sys/select.h>
#endif
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Recorder_OSS_Session construction:
CL_SoundProvider_Recorder_OSS_Session::CL_SoundProvider_Recorder_OSS_Session(int frequency) :
frequency(frequency), position(0)
{
dev_dsp_fd = open("/dev/dsp", O_RDONLY);
if (dev_dsp_fd == -1)
{
frag_size = frequency/2;
return;
// throw CL_Error("Could not open /dev/dsp. No sound will be available.");
}
#ifndef USE_DRIVER_FRAGSIZE
int frag_settings = 0x0003000b; // 0xMMMMSSSS
// (where MMMM = num fragments, SSSS = fragment size)
if (ioctl(dev_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &frag_settings))
{
CL_Log::log("debug", "ClanSound: Failed to set soundcard fragment size. Sound may have a long latency.");
}
#endif
format = AFMT_S16_NE;
ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format);
if (format != AFMT_S16_NE)
{
close(dev_dsp_fd);
throw CL_Error("Requires 16 bit soundcard. No sound input will be available.");
}
int stereo = 0;
ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
if (stereo != 0)
{
close(dev_dsp_fd);
throw CL_Error("ClanSound: Requires 16 bit mono input. No sound will be available.");
}
int speed = frequency;
ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
float percent_wrong = speed / (float) frequency;
if (percent_wrong < 0.90 || percent_wrong > 1.10)
{
close(dev_dsp_fd);
throw CL_Error("ClanSound: Mixing rate is not supported by soundcard.");
}
// Try to improve mixing performance by using the same mixing buffer size
// as the sound device does:
int err = ioctl(dev_dsp_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size);
if (err == -1)
{
CL_Log::log("debug", "ClanSound: Warning, Couldn't get sound device blocksize. Using 0.25 sec mixing buffer.");
frag_size = frequency/4; // 0.25 sec mixing buffer used.
}
}
CL_SoundProvider_Recorder_OSS_Session::~CL_SoundProvider_Recorder_OSS_Session()
{
}
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Recorder_OSS_Session attributes:
int CL_SoundProvider_Recorder_OSS_Session::get_num_samples() const
{
return 1;
}
int CL_SoundProvider_Recorder_OSS_Session::get_frequency() const
{
return frequency;
}
CL_SoundFormat CL_SoundProvider_Recorder_OSS_Session::get_format() const
{
return (CL_SoundFormat)format;
}
int CL_SoundProvider_Recorder_OSS_Session::get_num_channels() const
{
return 1;
}
int CL_SoundProvider_Recorder_OSS_Session::get_position() const
{
return position;
}
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Recorder_OSS_Session operations:
bool CL_SoundProvider_Recorder_OSS_Session::eof() const
{
return false;
}
void CL_SoundProvider_Recorder_OSS_Session::stop()
{
}
bool CL_SoundProvider_Recorder_OSS_Session::play()
{
return true;
}
bool CL_SoundProvider_Recorder_OSS_Session::set_position(int pos)
{
position = pos;
return true;
}
int CL_SoundProvider_Recorder_OSS_Session::get_data(void **data_ptr, int data_requested)
{
int len;
audio_buf_info info;
// todo: read samples, and only travel position by amount read.
int err = ioctl(dev_dsp_fd, SNDCTL_DSP_GETISPACE, &info);
if (err == -1)
{
CL_Log::log("debug", "ClanSound: fragments free not supported by device!?");
position = 0;
}
if(info.fragments == 0)
{
return 0;
}
else
{
len = read(dev_dsp_fd, data_ptr[0], data_requested);
}
position += len;
return position;
}
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Recorder_OSS_Session implementation:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -