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 _GRAUDIOSOURCE_H_
00038
#define _GRAUDIOSOURCE_H_
00039
00040 #define AUDIOINCHUNKSIZE 200
00041
00042
extern "C" {
00043
#include <sys/soundcard.h>
00044
#include <sys/ioctl.h>
00045
#include <fcntl.h>
00046
#include <unistd.h>
00047 }
00048
00049
#include <VrSource.h>
00050
#include <fstream>
00051
#include <algorithm>
00052
#include <string>
00053
00054
template<
class oType>
00055 class GrAudioSource :
public VrSource<oType> {
00056
protected:
00057 int audiofd;
00058 long format;
00059 std::string
device_name;
00060 oType scale_factor;
00061 int num_streams;
00062
public:
00063
virtual int work2(
VrSampleRange output,
void *o[]);
00064
virtual void initialize();
00065
00066 GrAudioSource(
double sampling_freq,
int streams,
double output_range = 32767,
00067
const char* dev =
"/dev/dsp")
00068 :
VrSource<
oType>(streams),
audiofd(-1),
device_name(dev),
num_streams(streams) {
00069
setSamplingFrequency (sampling_freq);
00070
setOutputSize (
AUDIOINCHUNKSIZE);
00071
scale_factor = (
oType) (32767 / output_range);
00072 }
00073
00074 virtual const char *
name() {
return "GrAudioSource"; }
00075
00076 virtual ~GrAudioSource() {close(
audiofd);}
00077 };
00078
00079
00080
template<
class oType>
void
00081 GrAudioSource<oType>::initialize()
00082 {
00083
int temp = 0x7fff0004;
00084
if(
audiofd==-1) {
00085
if ((
audiofd = open(
device_name.c_str(), O_RDONLY)) < 0) {
00086 cerr <<
"GrAudioSource: ";
00087 perror (
device_name.c_str ());
00088 exit(1);
00089 }
00090
if ((ioctl(
audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00091 fprintf (stderr,
"GrAudioSource: set fragment returned %d\n", errno);
00092 exit(1);
00093 }
00094 }
00095
00096
00097
00098
int format=AFMT_S16_NE;
00099
int origf=format;
00100
if((ioctl(
audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00101 cerr <<
"GrAudioSource: " <<
device_name <<
" IOCTL failed with errno " << errno <<
"\n";
00102 exit(1);
00103 }
00104
if(origf!=format) {
00105 fprintf (stderr,
"GrAudioSource: Warning: unable to support format %d\n", origf);
00106 fprintf (stderr,
" card requested %d instead.\n", format);
00107 }
00108
00109
00110
int channels = 2;
00111
if (ioctl (
audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00112 perror (
"GrAudioSink: SNDCTL_DSP_CHANNELS failed");
00113 exit (1);
00114 }
00115
00116
if (channels != 2){
00117 fprintf(stderr,
"GrAudioSource: could not set STEREO mode\n");
00118 exit(1);
00119 }
00120
00121
00122
00123
00124
int sf = (
int)
getSamplingFrequency();
00125 cerr <<
"GrAudioSource: Sampling frequency = "<<sf<<endl;
00126
00127
if ((ioctl(
audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00128 cerr <<
device_name <<
": Invalid sampling frequency...defaulting to 8 Khz\n";
00129 sf = 8000;
00130
if ((ioctl(
audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00131 fprintf (stderr,
"Couldn't even manage that...aborting\n");
00132 exit(1);
00133 }
00134 }
00135
if(sf!=
getSamplingFrequency())
00136 fprintf(stderr,
"GrAudioSource Warning: soundcard defaulted to %d Hz\n", sf);
00137 }
00138
00139
00140
template<
class oType>
int
00141 GrAudioSource<oType>::work2(
VrSampleRange output,
void *ao[])
00142 {
00143
sync (output.
index);
00144
00145
unsigned size = output.
size;
00146
oType **o = (
oType **)ao;
00147
00148
while(size > 0) {
00149
const unsigned N = 2048;
00150
short tmp[N*2];
00151
int nbytes = std::min (size, N) * (
sizeof(
short) * 2);
00152
00153
int count = read(
audiofd, tmp, nbytes);
00154
00155
if(count < 0) {
00156 perror (
"GrAudioSource");
00157 exit(1);
00158 }
00159
00160 assert ((count & ((
sizeof(
short) * 2) - 1)) == 0);
00161
00162
if(
num_streams == 1)
00163
for (
unsigned int i = 0; i < count / (
sizeof (
short) * 2); i++) {
00164 o[0][i] = (
oType)tmp[2*i]/
scale_factor;
00165 }
00166
else
00167
for (
unsigned int i = 0; i < count / (
sizeof (
short) * 2); i++) {
00168 o[0][i] = (
oType)tmp[2*i]/
scale_factor;
00169 o[1][i] = (
oType)tmp[2*i+1]/
scale_factor;
00170 }
00171
00172 size -= count / (
sizeof (
short) * 2);
00173 o[0] += count / (
sizeof (
short) * 2);
00174
if(
num_streams==2)
00175 o[1] += count / (
sizeof (
short) * 2);
00176 }
00177
return output.
size;
00178 }
00179
00180
template<>
int
00181
GrAudioSource<VrComplex>::work2(
VrSampleRange output,
void *ao[])
00182 {
00183
unsigned size = output.
size;
00184
VrComplex **o = (
VrComplex **)ao;
00185
00186
while(size > 0) {
00187
const unsigned N = 2048;
00188
short tmp[N*2];
00189
int nbytes = std::min (size, N) * (
sizeof(
short) * 2);
00190
00191
int count = read(audiofd, tmp, nbytes);
00192
00193
if(count < 0) {
00194 perror (
"GrAudioSource");
00195 exit(1);
00196 }
00197
00198 assert ((count & ((
sizeof(
short) * 2) - 1)) == 0);
00199
00200
for (
unsigned int i = 0; i < count / (
sizeof (
short) * 2); i++)
00201 o[0][i] =
VrComplex (tmp[2*i],tmp[2*i+1]) /
scale_factor;
00202
00203 size -= count / (
sizeof (
short) * 2);
00204 o[0] += count / (
sizeof (
short) * 2);
00205 }
00206
return output.
size;
00207 }
00208
00209
#endif