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 _GRAUDIOSINK_H_
00038
#define _GRAUDIOSINK_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 GrAudioSink :
public VrSink<iType> {
00055
protected:
00056 int audiofd;
00057 short *
buffer;
00058 std::string
device_name;
00059 iType scale_factor;
00060
public:
00061 virtual const char *
name() {
return "GrAudioSink"; }
00062
00063
virtual int work3(
VrSampleRange output,
00064
VrSampleRange inputs[],
void *i[]);
00065
00066
virtual void initialize();
00067
00068 GrAudioSink(
iType input_range = 32767,
const char* dev =
"/dev/dsp")
00069 :
audiofd(-1),
device_name(dev) {
00070
setOutputSize (
AUDIOOUTCHUNKSIZE);
00071
scale_factor = 32767 / input_range;
00072 }
00073
00074 virtual ~GrAudioSink() {
00075
delete []
buffer;
00076 close(
audiofd);
00077 }
00078 };
00079
00080
00081
template<
class iType>
void
00082 GrAudioSink<iType>::initialize()
00083 {
00084
if(
audiofd==-1) {
00085
int temp = 0x7fff0004;
00086
00087
if ((
audiofd = open(
device_name.c_str(), O_WRONLY)) < 0) {
00088 cerr <<
"GrAudioSink: ";
00089 perror (
device_name.c_str ());
00090 exit(1);
00091 }
00092
if ((ioctl(
audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00093 fprintf(stderr,
"GrAudioSink: set fragment returned %d\n", errno);
00094 exit(1);
00095 }
00096 }
00097
00098
00099
00100
00101
int format = AFMT_S16_NE;
00102
int origf=format;
00103
if((ioctl(
audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00104 cerr <<
"GrAudioSink: " <<
device_name <<
" IOCTL failed with " << errno <<
"\n";
00105 exit(1);
00106 }
00107
00108
if(origf!=format) {
00109 fprintf(stderr,
"GrAudioSink: Warning: unable to support format %d\n", origf);
00110 fprintf(stderr,
" card requested %d instead.\n", format);
00111 }
00112
00113
00114
int channels = 2;
00115
if (ioctl (
audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00116 perror (
"GrAudioSink: SNDCTL_DSP_CHANNELS failed");
00117 exit (1);
00118 }
00119
00120
if (channels != 2) {
00121 fprintf(stderr,
"GrAudioSink: could not set STEREO mode\n");
00122 exit(1);
00123 }
00124
00125
buffer =
new short[
getOutputSize() * 2];
00126
00127
int n =
getNumberInputs ();
00128 assert (n >= 1 && n <= 2);
00129
00130
if(n==2)
00131
if(
getInputSamplingFrequencyN(0)!=
getInputSamplingFrequencyN(1))
00132 fprintf(stderr,
"GrAudioSink Warning: left and right at different freq\n");
00133
00134
int sf = (
int)
getSamplingFrequency();
00135 printf(
"GrAudioSink: sampling frequency is %d\n",sf);
00136
00137
if ((ioctl(
audiofd, SNDCTL_DSP_SPEED, &sf)) < 0) {
00138 cerr <<
device_name <<
": invalid sampling frequency...defaulting to 8 Khz\n";
00139 sf = 8000;
00140
if ((ioctl(
audiofd,SNDCTL_DSP_SPEED, &sf)) < 0) {
00141 fprintf(stderr,
"Couldn't even manage that...aborting\n");
00142 exit(1);
00143 }
00144 }
00145
if (sf !=
getSamplingFrequency ())
00146 fprintf (stderr,
"GrAudioSink Warning: sound card default to %d Hz\n", sf);
00147 }
00148
00149
template<
class iType>
int
00150 GrAudioSink<iType>::work3(
VrSampleRange output,
VrSampleRange inputs[],
void *ai[])
00151 {
00152
iType **i = (
iType **)ai;
00153
unsigned size = output.
size;
00154
00155
00156 assert ((size %
getOutputSize()) == 0);
00157
00158
while(size > 0) {
00159
if(
getNumberInputs()==1) {
00160
for(
unsigned int k=0;k<
getOutputSize();k++) {
00161
buffer[2*k] = (
short)(
scale_factor * i[0][k]);
00162
buffer[2*k+1] = (
short)(
scale_factor * i[0][k]);
00163 }
00164 }
00165
else {
00166
for(
unsigned int k=0;k<
getOutputSize();k++) {
00167
buffer[2*k] = (
short)(
scale_factor * i[0][k]);
00168
buffer[2*k+1] = (
short)(
scale_factor * i[1][k]);
00169 }
00170 }
00171
00172
unsigned int count = write(
audiofd,
buffer,4*
getOutputSize());
00173
00174
if(count<0) {
00175 printf(
"AudioSink write error, errno: %d\n", errno);
00176 exit(1);
00177 }
00178
else {
00179
if(count!=4*
getOutputSize())
00180 printf(
"AudioSink: warning: not all bytes written!\n");
00181 }
00182 size-=
getOutputSize();
00183 i[0]+=
getOutputSize();
00184
if(
getNumberInputs()==2)
00185 i[1]+=
getOutputSize();
00186 }
00187
return output.
size;
00188 }
00189
00190
template<>
int
00191
GrAudioSink<VrComplex>::work3(
VrSampleRange output,
VrSampleRange inputs[],
void *ai[])
00192 {
00193
VrComplex **i = (
VrComplex **)ai;
00194
unsigned size = output.
size;
00195
00196
00197 assert ((size %
getOutputSize()) == 0);
00198
00199
if(
getNumberInputs()!=1)
00200 {
00201 cerr <<
"GrAudioSink: Can only output one VrComplex stream\n";
00202 exit(-1);
00203 }
00204
00205
while(size > 0) {
00206
for(
unsigned int k=0;k<
getOutputSize();k++) {
00207
buffer[2*k] = (
short)
real(scale_factor * i[0][k]);
00208
buffer[2*k+1] = (
short)
imag(scale_factor * i[0][k]);
00209 }
00210
00211
unsigned int count = write(audiofd,buffer,4*
getOutputSize());
00212
00213
if(count<0) {
00214 printf(
"AudioSink write error, errno: %d\n", errno);
00215 exit(1);
00216 }
00217
else {
00218
if(count!=4*
getOutputSize())
00219 printf(
"AudioSink: warning: not all bytes written!\n");
00220 }
00221 size-=
getOutputSize();
00222 i[0]+=
getOutputSize();
00223
if(
getNumberInputs()==2)
00224 i[1]+=
getOutputSize();
00225 }
00226
return output.
size;
00227 }
00228
00229
#endif