1 /* $Id: hw_audio.c,v 5.5 2008/09/14 18:04:37 lirc Exp $ */
3 /****************************************************************************
4 ** hw_audio.c **************************************************************
5 ****************************************************************************
7 * routines for using a IR receiver in microphone input using portaudio library
9 * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
10 * Copyright (C) 2001, 2002 Pavel Machek <pavel@ucw.cz>
11 * Copyright (C) 2002 Matthias Ringwald <ringwald@inf.ethz.ch>
13 * Distribute under GPL version 2 or later.
15 * Using ... hardware ...
31 #include <sys/types.h>
32 #include <sys/ioctl.h>
41 #include "ir_remote.h"
45 #include "hw_default.h"
47 static int ptyfd
; /* the pty */
49 /* PortAudio Includes */
50 #include <portaudio.h>
52 #define SAMPLE_RATE (44100)
53 #define NUM_CHANNELS (2)
54 #define DITHER_FLAG (0) /**/
56 /* Select sample format. */
57 #define PA_SAMPLE_TYPE paUInt8
58 typedef unsigned char SAMPLE
;
65 unsigned int lastCount
;
72 extern struct ir_remote
*repeat_remote
;
73 extern struct rbuf rec_buffer
;
81 void addCode( lirc_t data
)
83 write( master
, &data
, sizeof( lirc_t
) );
86 /* This routine will be called by the PortAudio engine when audio is needed.
87 ** It may be called at interrupt level on some machines so don't do anything
88 ** that could mess up the system like calling malloc() or free().
91 static int recordCallback( void *inputBuffer
, void *outputBuffer
,
92 unsigned long framesPerBuffer
,
93 PaStreamCallbackTimeInfo outTime
,
94 PaStreamCallbackFlags status
,
97 paTestData
*data
= (paTestData
*)userData
;
98 SAMPLE
*rptr
= (SAMPLE
*)inputBuffer
;
101 SAMPLE
*myPtr
= rptr
;
104 int samplerate
= SAMPLE_RATE
;
107 (void) outputBuffer
; /* Prevent unused variable warnings. */
110 for ( i
=0; i
< framesPerBuffer
; i
++, myPtr
++)
113 diff
= abs(data
->lastFrames
[0] - *myPtr
);
116 if (data
->pulseSign
== 0)
118 // we got the first signal, this is a PULSE
119 if ( *myPtr
> data
->lastFrames
[0] )
125 data
->pulseSign
= -1;
129 if (data
->lastCount
> 0)
131 if ( *myPtr
> data
->lastFrames
[0] && data
->lastSign
<= 0)
133 // printf("CHANGE ++ ");
136 time
= data
->lastCount
* 1000000 / samplerate
;
137 if (data
->lastSign
== data
->pulseSign
)
140 // printf("Pause: %d us, %d \n", time, data->lastCount);
144 addCode( time
| PULSE_BIT
);
145 // printf("Pulse: %d us, %d \n", time, data->lastCount);
150 else if ( *myPtr
< data
->lastFrames
[0] && data
->lastSign
>= 0)
152 // printf("CHANGE -- ");
155 time
= data
->lastCount
* 1000000 / samplerate
;
156 if (data
->lastSign
== data
->pulseSign
)
158 // printf("Pause: %d us, %d \n", time, data->lastCount);
163 // printf("Pulse: %d us, %d \n", time, data->lastCount);
164 addCode( time
| PULSE_BIT
);
165 }data
->lastCount
= 0;
170 if ( data
->lastCount
< 100000 )
175 data
->lastFrames
[0] = data
->lastFrames
[1];
176 data
->lastFrames
[1] = *myPtr
;
179 if (NUM_CHANNELS
== 2)
193 lirc_t
audio_readdata(lirc_t timeout
)
198 if (!waitfordata((long) timeout
))
201 ret
=read(hw
.fd
,&data
,sizeof(data
));
202 if(ret
!=sizeof(data
))
204 LOGPRINTF(1,"error reading from lirc");
221 PaStreamParameters inputParameters
;
226 LOGPRINTF(1,"hw_audio_init()");
229 logprintf(LOG_INFO
,"Initializing %s...",hw
.device
);
234 data
.lastFrames
[0] = 128;
235 data
.lastFrames
[1] = 128;
236 data
.lastFrames
[2] = 128;
241 err
= Pa_Initialize();
242 if( err
!= paNoError
) goto error
;
244 inputParameters
.device
= Pa_GetDefaultInputDevice(); /* default input device */
245 if (inputParameters
.device
== paNoDevice
) {
246 logprintf(LOG_ERR
, "No default input device");
249 inputParameters
.channelCount
= NUM_CHANNELS
; /* stereo input */
250 inputParameters
.sampleFormat
= PA_SAMPLE_TYPE
;
251 inputParameters
.suggestedLatency
=
252 Pa_GetDeviceInfo( inputParameters
.device
)->defaultLowInputLatency
;
253 inputParameters
.hostApiSpecificStreamInfo
= NULL
;
256 // Record some audio. --------------------------------------------
261 NULL
, // output parameters
263 512, // frames per buffer
268 if( err
!= paNoError
) goto error
;
271 if ( openpty( &master
, &ptyfd
, ptyName
, 0, 0) == -1)
273 logprintf(LOG_ERR
,"openpty failed");
274 logperror(LOG_ERR
,"openpty()");
278 // regular device file
279 if( tcgetattr( master
, &t
) < 0 ) {
280 logprintf(LOG_ERR
,"tcgetattr failed");
281 logperror(LOG_ERR
,"tcgetattr()");
286 // apply file descriptor options
287 if( tcsetattr( master
, TCSANOW
, &t
) < 0) {
288 logprintf(LOG_ERR
,"tcsetattr failed");
289 logperror(LOG_ERR
,"tcsetattr()");
292 flags
=fcntl(ptyfd
,F_GETFL
,0);
295 fcntl(ptyfd
,F_SETFL
,flags
|O_NONBLOCK
);
298 LOGPRINTF(LOG_INFO
,"PTY name: %s", ptyName
);
302 err
= Pa_StartStream( stream
);
303 if( err
!= paNoError
) goto error
;
309 logprintf(LOG_ERR
, "an error occured while using the portaudio stream" );
310 logprintf(LOG_ERR
, "error number: %d", err
);
311 logprintf(LOG_ERR
, "error message: %s", Pa_GetErrorText( err
) );
316 int audio_deinit(void)
320 LOGPRINTF(1,"hw_audio_deinit()");
323 err
= Pa_CloseStream( stream
);
324 if( err
!= paNoError
) goto error
;
328 // wair for terminaton
340 "an error occured while using the portaudio stream");
341 logprintf(LOG_ERR
,"error number: %d",err
);
342 logprintf(LOG_ERR
,"eError message: %s",Pa_GetErrorText(err
));
346 char *audio_rec(struct ir_remote
*remotes
)
348 if(!clear_rec_buffer()) return(NULL
);
349 return(decode_all(remotes
));
352 struct hardware hw_audio
=
354 "pty", /* simple device */
356 LIRC_CAN_REC_MODE2
, /* features */
358 LIRC_MODE_MODE2
, /* rec_mode */
360 audio_init
, /* init_func */
361 NULL
, /* config_func */
362 audio_deinit
, /* deinit_func */
363 NULL
, /* send_func */
364 audio_rec
, /* rec_func */
365 receive_decode
, /* decode_func */
366 NULL
, /* ioctl_func */