00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
#ifndef _VRAUDIOSINK_H_
00038
#define _VRAUDIOSINK_H_
00039
00040 #define AUDIOOUTCHUNKSIZE 64
00041
00042
extern "C" {
00043
#include <sys/soundcard.h>
00044
#include <sys/ioctl.h>
00045
#include <fcntl.h>
00046
#include <unistd.h>
00047
#include <assert.h>
00048 }
00049
#include <VrSink.h>
00050
#include <fstream>
00051
#include <string>
00052
00053
template<
class iType>
00054 class VrAudioSink :
public VrSink<iType> {
00055
protected:
00056 int audiofd;
00057 iType *
mixArray;
00058 bool convert_mono_to_stereo_p;
00059 std::string
device_name;
00060
00061
public:
00062 virtual const char *
name() {
return "VrAudioSink"; }
00063
00064
virtual int work3(
VrSampleRange output,
00065
VrSampleRange inputs[],
void *i[]);
00066
00067
virtual void initialize();
00068
00069 VrAudioSink(
const char* dev =
"/dev/dsp")
00070 :
audiofd(-1),
convert_mono_to_stereo_p(false),
device_name(dev) {
00071
setOutputSize (
AUDIOOUTCHUNKSIZE);
00072 }
00073
00074 virtual ~VrAudioSink() {
00075
delete []
mixArray;
00076 close(
audiofd);
00077 }
00078 };
00079
00080
00081
template<
class iType>
void
00082 VrAudioSink<iType>::initialize()
00083 {
00084
long format;
00085
00086
if(
audiofd==-1) {
00087
int temp = 0x7fff0004;
00088
00089
if ((
audiofd = open(
device_name.c_str(), O_WRONLY)) < 0) {
00090 cerr <<
"VrAudioSink: ";
00091 perror (
device_name.c_str ());
00092 exit(1);
00093 }
00094
if ((ioctl(
audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00095 fprintf(stderr,
"VrAudioSink: set fragment returned %d\n", errno);
00096 exit(1);
00097 }
00098 }
00099
00100
if(
sizeof(
iType)==1)
00101 format = AFMT_MU_LAW;
00102
if(
sizeof(
iType)==2)
00103 format = AFMT_S16_NE;
00104
else {
00105 fprintf(stderr,
"VrAudioSink: cannot handle data type of size %d\n",
sizeof (
iType));
00106 exit(1);
00107 }
00108
00109
00110
00111
00112
int origf=format;
00113
if((ioctl(
audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00114 cerr <<
"VrAudioSink: " <<
device_name <<
" IOCTL failed with " << errno <<
"\n";
00115 exit(1);
00116 }
00117
00118
if(origf!=format) {
00119 fprintf(stderr,
"VrAudioSink: Warning: unable to support format %d\n", origf);
00120 fprintf(stderr,
" card requested %ld instead.\n", format);
00121 }
00122
00123
00124
int n =
getNumberInputs ();
00125 assert (n >= 1 && n <= 2);
00126
00127
00128
00129
int channels = n;
00130
if (ioctl (
audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00131 perror (
"VrAudioSink: SNDCTL_DSP_CHANNELS failed");
00132 exit (1);
00133 }
00134
00135
if (channels != n){
00136
if (n == 2){
00137 fprintf(stderr,
"VrAudioSink: could not set STEREO mode\n");
00138 exit(1);
00139 }
00140
else {
00141
00142
convert_mono_to_stereo_p =
true;
00143 }
00144 }
00145
00146
if (
convert_mono_to_stereo_p)
00147
mixArray=
new iType[
getOutputSize()*2];
00148
else if(
getNumberInputs()==2) {
00149
mixArray=
new iType[
getOutputSize()*2];
00150
if(
getInputSamplingFrequencyN(0)!=
getInputSamplingFrequencyN(1))
00151 fprintf(stderr,
"VrAudioSink Warning: left and right at different freq\n");
00152 }
else
00153
mixArray =
NULL;
00154
00155
00156
int sf = (
int)
getSamplingFrequency();
00157 printf(
"VrAudioSink: sampling frequency is %d\n",sf);
00158
00159
if ((ioctl(
audiofd, SNDCTL_DSP_SPEED, &sf)) < 0) {
00160 cerr <<
device_name <<
": invalid sampling frequency...defaulting to 8 Khz\n";
00161 sf = 8000;
00162
if ((ioctl(
audiofd,SNDCTL_DSP_SPEED, &sf)) < 0) {
00163 fprintf(stderr,
"Couldn't even manage that...aborting\n");
00164 exit(1);
00165 }
00166 }
00167
if (sf !=
getSamplingFrequency ())
00168 fprintf (stderr,
"VrAudioSink Warning: sound card default to %d Hz\n", sf);
00169 }
00170
00171
template<
class iType>
int
00172 VrAudioSink<iType>::work3(
VrSampleRange output,
VrSampleRange inputs[],
void *ai[])
00173 {
00174
iType **i = (
iType **)ai;
00175
unsigned size = output.
size;
00176
int bytes =
getOutputSize()*
sizeof(
iType);
00177
iType *myPtr;
00178
00179
if(
getNumberInputs()==2 ||
convert_mono_to_stereo_p)
00180 bytes*=2;
00181
00182
00183 assert ((size %
getOutputSize()) == 0);
00184
00185
while(size > 0) {
00186 myPtr = i[0];
00187
00188
if(
getNumberInputs()==2) {
00189
for(
unsigned int ii=0;ii<
getOutputSize();ii++) {
00190
mixArray[ii*2] =i[0][ii];
00191
mixArray[ii*2+1]=i[1][ii];
00192 }
00193 myPtr=
mixArray;
00194 i[1]+=
getOutputSize();
00195 }
00196
00197
else if (
convert_mono_to_stereo_p){
00198
for(
unsigned int ii=0;ii<
getOutputSize();ii++) {
00199
mixArray[ii*2] =i[0][ii];
00200
mixArray[ii*2+1]=i[0][ii];
00201 }
00202 myPtr=
mixArray;
00203 }
00204
00205
int count = write(
audiofd,myPtr,bytes);
00206
if(count<0) {
00207 printf(
"AudioSink write error, errno: %d\n", errno);
00208 exit(1);
00209 }
else {
00210
if(count!=bytes)
00211 printf(
"AudioSink: warning: not all bytes written!\n");
00212 }
00213 size-=
getOutputSize();
00214 i[0]+=
getOutputSize();
00215 }
00216
return output.
size;
00217 }
00218
#endif