void PA_AudioIO_ALSA::enableRealTimeScheduling(bool enable){
    PaAlsa_EnableRealtimeScheduling(m_Stream, enable);
    m_isRealTime = enable;
    if(m_isRealTime){
        std::cout << "Real time scheduling is enabled." << std::endl;
    }
    else{
        std::cout << "Real time scheduling is disabled." << std::endl;
    }
}
Exemple #2
0
int run_filter(AudioOptions audio_options)
{
    PaStreamParameters input_parameters, output_parameters;
    PaStream *input_stream = NULL, *output_stream = NULL;
    PaError err = paNoError;
    CircularBuffer * output_buffer = CircularBuffer_create(audio_options.buffer_size);
    CircularBuffer * input_buffer = NULL;
    CircularBuffer * decoder_input = NULL;
    DecodingBuffer * decoder_buffer = NULL;

    int live_stream = !audio_options.wav_path || !strlen(audio_options.wav_path);

    OSFilter * filter =
        OSFilter_create(
                        audio_options.filters,
                        audio_options.num_filters,
                        2,
                        audio_options.filter_size,
                        audio_options.conv_multiple * (audio_options.filter_size - 1),
                        audio_options.input_scale
                        );
    if (!filter) {
        goto done;
    }

    if ((err = Pa_Initialize()) != paNoError) {
        goto done;
    }

    int step_size = audio_options.filter_size - 1;

    RecordCallbackMetadata record_data = {
        NULL,
        0,
        0,
        audio_options.number_of_channels,
        audio_options.enabled_channels,
        0
    };

    {
        int num_enabled_channels = 0;

        for (int i = 0; i < audio_options.number_of_channels; ++i) {
            if (audio_options.enabled_channels & (1 << i)) {
                num_enabled_channels++;
            }
        }
        if (num_enabled_channels != audio_options.enabled_channels) {
            record_data.stripe_input = 1;
        }
        if (num_enabled_channels == 0) {
            record_data.stripe_input = 0;
        }
    }

    if (record_data.stripe_input) {
        printf("striping record_data: %d channels with %d enabled flag\n",
               record_data.number_of_channels,
               record_data.enabled_channels
               );
    } else {
        printf("NOT striping record_data: %d channels with %d enabled flag\n",
               record_data.number_of_channels,
               record_data.enabled_channels
               );
    }

    if (live_stream) {
        input_buffer = CircularBuffer_create(audio_options.buffer_size);

        if (audio_options.decode_input) {
            decoder_input = CircularBuffer_create(audio_options.buffer_size);
            decoder_buffer = Decoding_new(decoder_input, input_buffer);
            record_data.buffer = decoder_input;
            if (!Decoding_start_ac3(decoder_buffer)) {
                printf("Failed to start ac3 decoder thread.\n");
                goto done;
            }
        } else {
            record_data.buffer = input_buffer;
        }

        input_parameters.device = audio_options.input_device;
        input_parameters.channelCount = 2;
        input_parameters.sampleFormat = PA_SAMPLE_TYPE;
        input_parameters.suggestedLatency = Pa_GetDeviceInfo(input_parameters.device)->defaultHighInputLatency;
        input_parameters.hostApiSpecificStreamInfo = NULL;

        err = Pa_OpenStream(
                            &input_stream,
                            &input_parameters,
                            NULL,
                            audio_options.sample_rate,
                            step_size,
                            paNoFlag,
                            recordCallback,
                            &record_data
                            );

        if (err != paNoError) {
            goto done;
        }

        record_data.start_time = currentTimeMillis();


#ifdef LINUX_ALSA
        PaAlsa_EnableRealtimeScheduling(input_stream, 1);
#endif

        if ((err = Pa_StartStream(input_stream)) != paNoError) {
            goto done;
        }
    } else {
        input_buffer = __read_audio_file(audio_options);
    }

    output_parameters.device = audio_options.output_device;
    if (audio_options.output_channels >= 6) {
        output_parameters.channelCount = audio_options.output_channels + 2;
    } else {
        output_parameters.channelCount = audio_options.output_channels;
    }
    output_parameters.sampleFormat = PA_SAMPLE_TYPE;
    output_parameters.suggestedLatency = Pa_GetDeviceInfo(output_parameters.device)->defaultLowOutputLatency;
    output_parameters.hostApiSpecificStreamInfo = NULL;

    PlaybackCallbackData playback_data = {
        output_buffer,
        output_parameters.channelCount
    };

    printf("output channels: %d\n", output_parameters.channelCount);

    err = Pa_OpenStream(
                        &output_stream,
                        NULL,
                        &output_parameters,
                        audio_options.sample_rate,
                        step_size,
                        paNoFlag,
                        playCallback,
                        &playback_data
                        );

    if (err != paNoError) {
        goto done;
    }

#ifdef LINUX_ALSA
    PaAlsa_EnableRealtimeScheduling(output_stream, 1);
#endif

    if ((err = Pa_StartStream(output_stream)) != paNoError) {
        goto done;
    }

    int output_scale = output_parameters.channelCount / 2;
    int frame_print_interval = DEBUG_PRINT_INTERVAL_MILLIS * audio_options.sample_rate / 1000;
    int current_frame = 0;

    while (true) {
        if ((err = Pa_IsStreamActive(output_stream)) != 1) {
            break;
        }
        if (input_stream && (err = Pa_IsStreamActive(input_stream)) != 1) {
            break;
        }
        current_frame += OSFilter_execute(filter, input_buffer, output_buffer);
        if (audio_options.print_debug && current_frame > frame_print_interval) {
            current_frame -= frame_print_interval;

            if (!is_parent_running(audio_options.parent_thread_ident)) {
                printf("Parent thread is dead. Shutting down now.\n");
                fflush(stdout);
                goto done;
            }

            if (!audio_options.print_debug) {
                continue;
            }
            long frame_difference = (CircularBuffer_lag(input_buffer) + CircularBuffer_lag(output_buffer) / output_scale) / 2;
            float lag = (float)(frame_difference) / audio_options.sample_rate * 1000;
            printf("%lu\t%lu\t%lu\t%fms\n",
                   input_buffer->offset_producer,
                   output_buffer->offset_consumer / output_scale,
                   frame_difference, lag
                   );

            if (live_stream && (lag > audio_options.lag_reset_limit * 1000)) {
                printf("Resetting to latest due to high lag.\n");
                CircularBuffer_fastforward(input_buffer, audio_options.filter_size * 2);
                CircularBuffer_fastforward(output_buffer, 0);
            }
            fflush(stdout);
        }
    }
    if (err < 0) {
        goto done;
    }

done:
    if (output_stream) {
        Pa_CloseStream(output_stream);
    }
    if (input_stream) {
        Pa_CloseStream(input_stream);
    }
    Pa_Terminate();
    if (input_buffer) {
        CircularBuffer_destroy(input_buffer);
    }
    CircularBuffer_destroy(output_buffer);
    if (decoder_input) {
        CircularBuffer_destroy(decoder_input);
    }
    if (decoder_buffer) {
        Decoding_free(decoder_buffer);
    }

    OSFilter_destroy(filter);

    if (err != paNoError) {
        fprintf(stdout, "An error occured while using the portaudio stream\n");
        fprintf(stdout, "Error number: %d\n", err);
        fprintf(stdout, "Error message: %s\n", Pa_GetErrorText(err));
        fflush(stdout);
        err = 1;
    }
    return err;
}
Exemple #3
0
PaError OpenStream(PaStream **mStream, PaDeviceIndex Device, double Rate, void* Sound, double &dLatency, PaStreamCallback Callback)
{
	PaStreamParameters outputParams;

	outputParams.device = Device;
	outputParams.channelCount = 2;
	outputParams.sampleFormat = paFloat32;

	if (!Configuration::GetConfigf("UseHighLatency", "Audio"))
		outputParams.suggestedLatency = Pa_GetDeviceInfo(outputParams.device)->defaultLowOutputLatency;
	else
		outputParams.suggestedLatency = Pa_GetDeviceInfo(outputParams.device)->defaultHighOutputLatency;


#ifndef WIN32

	outputParams.hostApiSpecificStreamInfo = NULL;

#else
	PaWasapiStreamInfo StreamInfo;
	PaWinDirectSoundStreamInfo DSStreamInfo;
	if (UseWasapi)
	{
		outputParams.hostApiSpecificStreamInfo = &StreamInfo;
		StreamInfo.hostApiType = paWASAPI;
		StreamInfo.size = sizeof(PaWasapiStreamInfo);
		StreamInfo.version = 1;
		if (!Configuration::GetConfigf("WasapiDontUseExclusiveMode", "Audio"))
		{
			StreamInfo.threadPriority = eThreadPriorityProAudio;
			StreamInfo.flags = paWinWasapiExclusive;
		}
		else
		{
			StreamInfo.threadPriority = eThreadPriorityAudio;
			StreamInfo.flags = 0;
		}

		StreamInfo.hostProcessorOutput = NULL;
		StreamInfo.hostProcessorInput = NULL;
	}
	else
	{
		outputParams.hostApiSpecificStreamInfo = &DSStreamInfo;

		DSStreamInfo.size = sizeof(PaWinDirectSoundStreamInfo);
		DSStreamInfo.hostApiType = paDirectSound;
		DSStreamInfo.version = 2;
		DSStreamInfo.flags = 0;
	}
#endif

	dLatency = outputParams.suggestedLatency;

	// fire up portaudio
	PaError Err = Pa_OpenStream(mStream, NULL, &outputParams, Rate, 0, paClipOff, Callback, (void*)Sound);

	if (Err)
	{
		Log::Logf("%ls\n", Utility::Widen(Pa_GetErrorText(Err)).c_str());
		Log::Logf("Device Selected %d\n", Device);
	}
#ifdef LINUX
	else
	{
		Log::Logf("Audio: Enabling real time scheduling\n");
		PaAlsa_EnableRealtimeScheduling( mStream, true );
	}	
#endif

	return Err;
}