Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

oss.cpp

Go to the documentation of this file.
00001 /*
00002         ClanSound, sound mixing library written for ClanLib.
00003         Copyright (c)1998 Magnus Norddahl / ClanSoft.
00004 
00005         OSS Documentation can be found at http://www.opensound.com
00006 */
00007 
00008 #include "Core/precomp.h"
00009 
00010 #ifdef USE_CLANSOUND
00011 
00012 #include <unistd.h>
00013 #include <fcntl.h>
00014 #include <sys/ioctl.h>
00015 #include <sys/soundcard.h>
00016 #include <iostream>
00017 
00018 #include <API/Core/System/error.h>
00019 #include "API/Core/System/cl_assert.h"
00020 #include "API/Core/System/system.h"
00021 #include <Sound/Sound/ClanSound/oss.h>
00022 
00023 // If USE_DRIVER_FRAGSIZE is defined, we use the fragsize (and number of them)
00024 // used by the soundcard driver. This is not as efficient as using our own
00025 // settings - mainly provided for debugging.
00026 // #define USE_DRIVER_FRAGSIZE
00027 
00028 bool has_sound = true;
00029 
00030 CL_CSOutput::CL_CSOutput()
00031 {
00032         dev_dsp_fd = open("/dev/dsp", O_WRONLY);
00033         if (dev_dsp_fd == -1)
00034         {
00035                 has_sound = false;
00036                 frag_size = 22050/2;
00037                 return;
00038 //              throw CL_Error("Could not open /dev/dsp. No sound will be available.");
00039         }
00040         
00041 #ifndef USE_DRIVER_FRAGSIZE
00042         int frag_settings = 0x0003000b; // 0xMMMMSSSS
00043                 // (where MMMM = num fragments, SSSS = fragment size)
00044 
00045         if (ioctl(dev_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &frag_settings))
00046         {
00047                 std::cout << "ClanSound: Failed to set soundcard fragment size. Sound may have a long latency." << std::endl;
00048         }
00049 
00050 #endif
00051         
00052         int format = AFMT_S16_LE;
00053         ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format);
00054         if (format != AFMT_S16_LE)
00055         {
00056                 close(dev_dsp_fd);
00057                 throw CL_Error("Requires 16 bit soundcard. No sound will be available.");
00058         }
00059         
00060         int stereo = 1;
00061         ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
00062         if (stereo != 1)
00063         {
00064                 close(dev_dsp_fd);
00065                 throw CL_Error("ClanSound: Requires 16 bit stereo capable soundcard. No sound will be available.");
00066         }
00067         
00068         int speed = 22050;
00069         ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
00070 
00071         float percent_wrong = speed / (float) 22050;
00072         if (percent_wrong < 0.90 || percent_wrong > 1.10)
00073         {
00074                 close(dev_dsp_fd);
00075                 throw CL_Error("ClanSound: Mixing rate (22.05 kHz) not supported by soundcard.");
00076         }
00077         
00078         // Try to improve mixing performance by using the same mixing buffer size
00079         // as the sound device does:
00080         int err = ioctl(dev_dsp_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size);
00081         if (err == -1)
00082         {
00083                 std::cout << "ClanSound: Warning, Couldn't get sound device blocksize. Using 0.25 sec mixing buffer." << std::endl;
00084                 frag_size = 22050/2; // 0.25 sec mixing buffer used.
00085         }
00086 
00087         audio_buf_info info;
00088         ioctl(dev_dsp_fd, SNDCTL_DSP_GETOSPACE, &info);
00089 }
00090 
00091 CL_CSOutput::~CL_CSOutput()
00092 {
00093         if (dev_dsp_fd != -1) close(dev_dsp_fd);
00094 }
00095 
00096 void CL_CSOutput::silence()
00097 // Called when we have no samples to play - and wants to tell the soundcard
00098 // about this possible event.
00099 {
00100         ioctl(dev_dsp_fd, SNDCTL_DSP_POST, 0);
00101 }
00102 
00103 bool CL_CSOutput::is_full()
00104 // Returns true if all fragments are filled with data.
00105 {
00106         if (!has_sound) return false;
00107         audio_buf_info info;
00108         int err = ioctl(dev_dsp_fd, SNDCTL_DSP_GETOSPACE, &info);
00109         if (err == -1)
00110         {
00111                 std::cout << "ClanSound: fragments free not supported by device!?" << std::endl;
00112                 return false; // not supported by device!?
00113         }
00114 
00115         if (info.fragments == 0) return true;
00116         return false;
00117 }
00118 
00119 int CL_CSOutput::get_frag_size()
00120 // Returns the buffer size used by device (returned as num [stereo] samples).
00121 {
00122         return frag_size/4;
00123 }
00124 
00125 void CL_CSOutput::write_fragment(short *data)
00126 // Writes a fragment to the soundcard.
00127 {
00128         write(dev_dsp_fd, data, frag_size);
00129 }
00130 
00131 void CL_CSOutput::wait()
00132 {
00133         if(!has_sound)
00134         {
00135                 CL_System::sleep(100);
00136                 return;
00137         }
00138 
00139         fd_set wfds;
00140 
00141         FD_ZERO(&wfds);
00142         FD_SET(dev_dsp_fd, &wfds);
00143 
00144         /*int retval =*/ select(dev_dsp_fd+1, NULL, &wfds, NULL, NULL);
00145 //      cl_assert(retval != -1);
00146 }
00147 
00148 #endif

Generated at Wed Apr 4 19:54:02 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001