|
|
1.1 root 1: /*
2: Hatari - microphone.c
3: microphone (jack connector) emulation (Falcon mode only)
4:
5: This file is distributed under the GNU Public License, version 2 or at
6: your option any later version. Read the file gpl.txt for details.
7:
8: This program uses the PortAudio Portable Audio Library.
9: For more information see: http://www.portaudio.com
10: Copyright (c) 1999-2000 Ross Bencina and Phil Burk
11: */
12:
13: #include "main.h"
14:
15: #if HAVE_PORTAUDIO
16:
17: #include <portaudio.h>
18: #include "microphone.h"
1.1.1.2 ! root 19: #include "configuration.h"
1.1 root 20: #include "crossbar.h"
1.1.1.2 ! root 21: #include "log.h"
1.1 root 22:
23: #define FRAMES_PER_BUFFER (64)
24:
25: /* Static functions */
1.1.1.2 ! root 26: static bool Microphone_Error (void);
! 27: static bool Microphone_Terminate(void);
1.1 root 28:
29: static int Microphone_Callback (const void *inputBuffer, void *outputBuffer,
30: unsigned long framesPerBuffer,
31: const PaStreamCallbackTimeInfo* timeInfo,
32: PaStreamCallbackFlags statusFlags,
33: void *userData);
34:
35: /* Static datas */
36: static PaStreamParameters micro_inputParameters;
37: static PaStream *micro_stream;
38: static PaError micro_err;
39:
40: static int micro_sampleRate;
41: static Sint16 micro_buffer_L[FRAMES_PER_BUFFER]; /* left buffer */
42: static Sint16 micro_buffer_R[FRAMES_PER_BUFFER]; /* right buffer */
43:
44:
45: /* This routine will be called by the PortAudio engine when audio is needed.
46: ** It may be called at interrupt level on some machines so don't do anything
47: ** that could mess up the system like calling malloc() or free().
48: */
49: static int Microphone_Callback (const void *inputBuffer, void *outputBuffer,
50: unsigned long framesPerBuffer,
51: const PaStreamCallbackTimeInfo* timeInfo,
52: PaStreamCallbackFlags statusFlags,
53: void *userData)
54: {
55: unsigned int i;
56: const Sint16 *in = inputBuffer;
57:
58: Sint16 *out_L = (Sint16*)micro_buffer_L;
59: Sint16 *out_R = (Sint16*)micro_buffer_R;
60:
61: if (inputBuffer == NULL) {
62: memset(micro_buffer_L, 0, sizeof(micro_buffer_L));
63: memset(micro_buffer_R, 0, sizeof(micro_buffer_R));
64: }
65: else {
66: for (i=0; i<framesPerBuffer; i++) {
67: *out_L ++ = *in++; /* left data */
68: *out_R ++ = *in++; /* right data */
69: }
70: }
71:
72: /* send buffer to crossbar */
73: Crossbar_GetMicrophoneDatas(micro_buffer_L, micro_buffer_R, framesPerBuffer);
74:
75: /* get Next Microphone datas */
76: return paContinue;
77: }
78:
79:
80: /*******************************************************************/
81:
82: /**
83: * Microphone (jack) inits : init portaudio microphone emulation
84: * - sampleRate : system sound frequency
1.1.1.2 ! root 85: * return true on success, false on error or if mic disabled
1.1 root 86: */
1.1.1.2 ! root 87: bool Microphone_Start(int sampleRate)
1.1 root 88: {
1.1.1.2 ! root 89: if (!ConfigureParams.Sound.bEnableMicrophone) {
! 90: Log_Printf(LOG_DEBUG, "Microphone: Disabled\n");
! 91: return false;
! 92: }
! 93:
1.1 root 94: micro_sampleRate = sampleRate;
95:
96: /* Initialize portaudio */
97: micro_err = Pa_Initialize();
98: if (micro_err != paNoError) {
1.1.1.2 ! root 99: return Microphone_Error();
1.1 root 100: }
101:
102: /* Initialize microphone parameters */
103: micro_inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
104: if (micro_inputParameters.device == paNoDevice) {
1.1.1.2 ! root 105: Log_Printf(LOG_WARN, "Microphone: No input device found.\n");
1.1 root 106: Microphone_Terminate();
1.1.1.2 ! root 107: return false;
1.1 root 108: }
109:
110: micro_inputParameters.channelCount = 2; /* stereo input */
111: micro_inputParameters.sampleFormat = paInt16; /* 16 bits sound */
112: micro_inputParameters.suggestedLatency = Pa_GetDeviceInfo (micro_inputParameters.device)->defaultLowInputLatency;
113: micro_inputParameters.hostApiSpecificStreamInfo = NULL;
114:
115: /* Open Microphone stream */
116: micro_err = Pa_OpenStream (
117: µ_stream,
118: µ_inputParameters,
119: NULL,
120: micro_sampleRate,
121: FRAMES_PER_BUFFER,
122: 0, /* paClipOff, we won't output out of range samples so don't bother clipping them */
123: Microphone_Callback,
124: NULL);
125: if (micro_err != paNoError) {
1.1.1.2 ! root 126: return Microphone_Error();
1.1 root 127: }
128:
129: /* Start microphone recording */
130: micro_err = Pa_StartStream( micro_stream );
131: if (micro_err != paNoError) {
1.1.1.2 ! root 132: return Microphone_Error();
1.1 root 133: }
1.1.1.2 ! root 134:
! 135: return true;
1.1 root 136: }
137:
138: /**
139: * Microphone (jack) Error : display current portaudio error
140: */
1.1.1.2 ! root 141: static bool Microphone_Error(void)
1.1 root 142: {
143: fprintf (stderr, "An error occured while using the portaudio stream\n");
144: fprintf (stderr, "Error number: %d\n", micro_err);
145: fprintf (stderr, "Error message: %s\n", Pa_GetErrorText (micro_err));
146:
147: Microphone_Terminate();
1.1.1.2 ! root 148: return false;
1.1 root 149: }
150:
151: /**
152: * Microphone (jack) Terminate : terminate the microphone emulation
1.1.1.2 ! root 153: * return true for success
1.1 root 154: */
1.1.1.2 ! root 155: static bool Microphone_Terminate(void)
1.1 root 156: {
1.1.1.2 ! root 157: micro_stream = NULL; /* catch erronous use */
! 158:
1.1 root 159: micro_err = Pa_Terminate();
160: if (micro_err != paNoError) {
161: fprintf (stderr, "PortAudio error: %s\n", Pa_GetErrorText(micro_err));
1.1.1.2 ! root 162: return false;
1.1 root 163: }
1.1.1.2 ! root 164:
! 165: return true;
1.1 root 166: }
167:
168: /**
169: * Microphone (jack) stop : stops the current recording
1.1.1.2 ! root 170: * return true for success, false for error
1.1 root 171: */
1.1.1.2 ! root 172: bool Microphone_Stop(void)
1.1 root 173: {
174: /* Close Microphone stream */
175: micro_err = Pa_CloseStream(micro_stream);
176: if (micro_err != paNoError) {
1.1.1.2 ! root 177: return Microphone_Error();
1.1 root 178: }
179:
180: return Microphone_Terminate();
181: }
182:
183: #endif /* HAVE PORTAUDIO */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.