|
4 | 4 | #include <portaudio.h>
|
5 | 5 |
|
6 | 6 | #define SAMPLE_SILENCE -32767
|
7 |
| -#define PA_SAMPLE_TYPE paInt16 |
8 | 7 | typedef short SAMPLE;
|
9 | 8 |
|
10 | 9 | typedef struct {
|
@@ -39,9 +38,9 @@ static int recordCallback(const void *inputBuffer, void *outputBuffer,
|
39 | 38 | }
|
40 | 39 |
|
41 | 40 | if (inputBuffer == NULL)
|
42 |
| - write_to_cava_input_buffers(framesToCalc * 2, silence_ptr, audio); |
| 41 | + write_to_cava_input_buffers(framesToCalc * audio->channels, silence_ptr, audio); |
43 | 42 | else
|
44 |
| - write_to_cava_input_buffers(framesToCalc * 2, rptr, audio); |
| 43 | + write_to_cava_input_buffers(framesToCalc * audio->channels, rptr, audio); |
45 | 44 |
|
46 | 45 | data->frameIndex += framesToCalc;
|
47 | 46 | if (finished == paComplete) {
|
@@ -92,6 +91,7 @@ void *input_portaudio(void *audiodata) {
|
92 | 91 | i + 1, deviceInfo->name, deviceInfo->maxInputChannels,
|
93 | 92 | deviceInfo->maxOutputChannels, deviceInfo->defaultSampleRate);
|
94 | 93 | }
|
| 94 | + printf("See cava readme for more information on how to capture audio.\n"); |
95 | 95 | exit(EXIT_SUCCESS);
|
96 | 96 | } else if (!strcmp(audio->source, "auto")) {
|
97 | 97 | deviceNum = Pa_GetDefaultInputDevice();
|
@@ -120,30 +120,66 @@ void *input_portaudio(void *audiodata) {
|
120 | 120 | }
|
121 | 121 | }
|
122 | 122 | inputParameters.device = deviceNum;
|
| 123 | + const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(deviceNum); |
| 124 | + if (deviceInfo->maxInputChannels == 0) { |
| 125 | + fprintf(stderr, "Error: selected device has no input channels!\n Use \"list\" as source to " |
| 126 | + "get a list of available sources.\n"); |
| 127 | + exit(EXIT_FAILURE); |
| 128 | + } |
123 | 129 |
|
124 | 130 | // set parameters
|
125 |
| - data.maxFrameIndex = audio->input_buffer_size * 1024 / 2; |
| 131 | + inputParameters.channelCount = deviceInfo->maxInputChannels; |
| 132 | + audio->channels = deviceInfo->maxInputChannels; |
| 133 | + if (audio->channels > 2) |
| 134 | + audio->channels = 2; |
| 135 | + |
| 136 | + data.maxFrameIndex = audio->input_buffer_size * 1024 / audio->channels; |
126 | 137 | data.recordedSamples = (SAMPLE *)malloc(2 * data.maxFrameIndex * sizeof(SAMPLE));
|
127 | 138 | if (data.recordedSamples == NULL) {
|
128 | 139 | fprintf(stderr, "Error: failure in memory allocation!\n");
|
129 | 140 | exit(EXIT_FAILURE);
|
130 | 141 | } else
|
131 | 142 | memset(data.recordedSamples, 0x00, 2 * data.maxFrameIndex);
|
132 | 143 |
|
133 |
| - inputParameters.channelCount = 2; |
134 |
| - inputParameters.sampleFormat = PA_SAMPLE_TYPE; |
| 144 | + double sampleRate = deviceInfo->defaultSampleRate; |
| 145 | + audio->rate = sampleRate; |
| 146 | + |
| 147 | + PaSampleFormat sampleFormats[] = {paInt16, paInt24, paInt32, paFloat32, |
| 148 | + paInt8, paUInt8, paInt16}; |
| 149 | + int sampleBits[] = { |
| 150 | + 16, 24, 32, 32, 8, 8, |
| 151 | + }; |
| 152 | + |
| 153 | + for (int i = 0; i < 7; i++) { |
| 154 | + inputParameters.sampleFormat = sampleFormats[i]; |
| 155 | + PaError err = Pa_IsFormatSupported(&inputParameters, NULL, sampleRate); |
| 156 | + if (err == paFormatIsSupported) { |
| 157 | + audio->format = sampleBits[i]; |
| 158 | + if (i == 3) |
| 159 | + audio->IEEE_FLOAT = 1; |
| 160 | + break; |
| 161 | + } |
| 162 | + } |
| 163 | + |
135 | 164 | inputParameters.suggestedLatency =
|
136 | 165 | Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
|
137 | 166 | inputParameters.hostApiSpecificStreamInfo = NULL;
|
138 | 167 |
|
139 | 168 | // set it to work
|
140 |
| - err = Pa_OpenStream(&stream, &inputParameters, NULL, audio->rate, audio->input_buffer_size / 2, |
141 |
| - paClipOff, recordCallback, &data); |
| 169 | + err = |
| 170 | + Pa_OpenStream(&stream, &inputParameters, NULL, sampleRate, |
| 171 | + audio->input_buffer_size / audio->channels, paClipOff, recordCallback, &data); |
142 | 172 | if (err != paNoError) {
|
143 |
| - fprintf(stderr, "Error: failure in opening stream (%s)\n", Pa_GetErrorText(err)); |
| 173 | + fprintf(stderr, |
| 174 | + "Error: failure in opening stream (device: %d), (error: %s). Use \"list\" as souce " |
| 175 | + "to get a list of " |
| 176 | + "available sources.\n", |
| 177 | + deviceNum + 1, Pa_GetErrorText(err)); |
144 | 178 | exit(EXIT_FAILURE);
|
145 | 179 | }
|
146 | 180 |
|
| 181 | + audio->threadparams = 0; |
| 182 | + |
147 | 183 | // main loop
|
148 | 184 | while (1) {
|
149 | 185 | // start recording
|
|
0 commit comments