예제 #1
0
void _pa_open(void) {
	PaStreamParameters outputParameters;
	PaError err = paNoError;
	int device_id;

	if (pa.stream) {
		if ((err = Pa_CloseStream(pa.stream)) != paNoError) {
			LOG_WARN("error closing stream: %s", Pa_GetErrorText(err));
		}
	}

	if (output.state == OUTPUT_OFF) {
		// we get called when transitioning to OUTPUT_OFF to create the probe thread
		// set err to avoid opening device and logging messages
		err = 1;

	} else if ((device_id = pa_device_id(output.device)) == -1) {
		LOG_INFO("device %s not found", output.device);
		err = 1;

	} else {

		outputParameters.device = device_id;
		outputParameters.channelCount = 2;
		outputParameters.sampleFormat = paInt32;
		outputParameters.suggestedLatency =
			output.latency ? (double)output.latency/(double)1000 : Pa_GetDeviceInfo(outputParameters.device)->defaultHighOutputLatency;
		outputParameters.hostApiSpecificStreamInfo = NULL;
		
#if OSX
		// enable pro mode which aims to avoid resampling if possible
		// see http://code.google.com/p/squeezelite/issues/detail?id=11 & http://code.google.com/p/squeezelite/issues/detail?id=37
		// command line controls osx_playnice which is -1 if not specified, 0 or 1 - choose playnice if -1 or 1
		PaMacCoreStreamInfo macInfo;
		unsigned long streamInfoFlags;
	 	if (output.osx_playnice) {
			LOG_INFO("opening device in PlayNice mode");
			streamInfoFlags = paMacCorePlayNice;
		} else {
			LOG_INFO("opening device in Pro mode");
			streamInfoFlags = paMacCorePro;
		}
		PaMacCore_SetupStreamInfo(&macInfo, streamInfoFlags);
		outputParameters.hostApiSpecificStreamInfo = &macInfo;
#endif
	}

	if (!err &&
		(err = Pa_OpenStream(&pa.stream, NULL, &outputParameters, (double)output.current_sample_rate, paFramesPerBufferUnspecified,
							 paPrimeOutputBuffersUsingStreamCallback | paDitherOff, pa_callback, NULL)) != paNoError) {
		LOG_WARN("error opening device %i - %s : %s", outputParameters.device, Pa_GetDeviceInfo(outputParameters.device)->name, 
				 Pa_GetErrorText(err));
	}

	if (!err) {
		LOG_INFO("opened device %i - %s at %u latency %u ms", outputParameters.device, Pa_GetDeviceInfo(outputParameters.device)->name,
				 (unsigned int)Pa_GetStreamInfo(pa.stream)->sampleRate, (unsigned int)(Pa_GetStreamInfo(pa.stream)->outputLatency * 1000));

		pa.rate = output.current_sample_rate;

		if ((err = Pa_SetStreamFinishedCallback(pa.stream, pa_stream_finished)) != paNoError) {
			LOG_WARN("error setting finish callback: %s", Pa_GetErrorText(err));
		}
	
		if ((err = Pa_StartStream(pa.stream)) != paNoError) {
			LOG_WARN("error starting stream: %s", Pa_GetErrorText(err));
		}
	}

	if (err && !monitor_thread_running) {
		vis_stop();

		// create a thread to check for output state change or device return
#if LINUX || OSX
		pthread_create(&monitor_thread, NULL, pa_monitor, NULL);
#endif
#if WIN
		monitor_thread = CreateThread(NULL, OUTPUT_THREAD_STACK_SIZE, (LPTHREAD_START_ROUTINE)&pa_monitor, NULL, 0, NULL);
#endif
	}

	output.error_opening = !err;
}
    bool open() {
        if(stream) close();
        assert(stream == NULL);

        PaStreamParameters outputParameters;

#if defined(__APPLE__)
        PaMacCoreStreamInfo macInfo;
        PaMacCore_SetupStreamInfo( &macInfo,
                                   paMacCorePlayNice | paMacCorePro );
        outputParameters.hostApiSpecificStreamInfo = &macInfo;
#elif defined(__LINUX__)
        // TODO: if we have PaAlsa_EnableRealtimeScheduling in portaudio,
        // we can call that to enable RT priority with ALSA.
        // We could check dynamically via dsym.
        outputParameters.hostApiSpecificStreamInfo = NULL;
#else
        outputParameters.hostApiSpecificStreamInfo = NULL;
#endif

        outputParameters.device = Pa_GetDefaultOutputDevice();
        if (outputParameters.device == paNoDevice) {
            PyErr_SetString(PyExc_RuntimeError, "Pa_GetDefaultOutputDevice didn't returned a device");
            return false;
        }
        outputParameters.channelCount = player->outNumChannels;
        outputParameters.sampleFormat = OutPaSampleFormat<OUTSAMPLE_t>::format;

        unsigned long bufferSize = (player->outSamplerate * player->outNumChannels / 1000) * LATENCY_IN_MS / 4;
        if(bufferSize == paFramesPerBufferUnspecified)
            outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
        else
            outputParameters.suggestedLatency = LATENCY_IN_MS / 1000.0;

        // Note about framesPerBuffer:
        // Earlier, we used (2048 * 5 * OUTSAMPLEBYTELEN) which caused
        // some random more or less rare cracking noises.
        // See here: https://github.com/albertz/music-player/issues/35
        // This doesn't seem to happen with paFramesPerBufferUnspecified.

        PaError ret = Pa_OpenStream(
                          &stream,
                          NULL, // no input
                          &outputParameters,
                          player->outSamplerate, // sampleRate
                          bufferSize,
                          paClipOff | paDitherOff,
#if USE_PORTAUDIO_CALLBACK
                          &paStreamCallback,
#else
                          NULL,
#endif
                          this //void *userData
                      );

        if(ret != paNoError) {
            PyErr_Format(PyExc_RuntimeError, "Pa_OpenStream failed: (err %i) %s", ret, Pa_GetErrorText(ret));
            if(stream)
                close();
            return false;
        }

        needRealtimeReset = true;
        Pa_StartStream(stream);

#if !USE_PORTAUDIO_CALLBACK
        audioThread.func = boost::bind(&OutStream::audioThreadProc, this, _1, _2);
        audioThread.start();
#endif
        return true;
    }
예제 #3
0
int main(void)
{
    PaStreamParameters outputParameters;
    PaStream *stream;
    PaError err;
    paTestData data;
#ifdef __APPLE__
    PaMacCoreStreamInfo macInfo;
    const SInt32 channelMap[4] = { -1, -1, 0, 1 };
#endif
    int i;

    
    printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
    printf("Output will be mapped to channels 2 and 3 instead of 0 and 1.\n");
    
    /* initialise sinusoidal wavetable */
    for( i=0; i<TABLE_SIZE; i++ )
    {
        data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
    }
    data.left_phase = data.right_phase = 0;
    
    err = Pa_Initialize();
    if( err != paNoError ) goto error;

    /** setup host specific info */
#ifdef __APPLE__
    PaMacCore_SetupStreamInfo( &macInfo, paMacCorePlayNice );
    PaMacCore_SetupChannelMap( &macInfo, channelMap, 4 );

    for( i=0; i<4; ++i )
       printf( "channel %d name: %s\n", i, PaMacCore_GetChannelName( Pa_GetDefaultOutputDevice(), i, false ) );
#else
    printf( "Channel mapping not supported on this platform. Reverting to normal sine test.\n" );
#endif

    outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
    if (outputParameters.device == paNoDevice) {
        fprintf(stderr,"Error: No default output device.\n");
        goto error;
    }
    outputParameters.channelCount = 2;       /* stereo output */
    outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
#ifdef __APPLE__
    outputParameters.hostApiSpecificStreamInfo = &macInfo;
#else
    outputParameters.hostApiSpecificStreamInfo = NULL;
#endif

    err = Pa_OpenStream(
              &stream,
              NULL, /* no input */
              &outputParameters,
              SAMPLE_RATE,
              FRAMES_PER_BUFFER,
              paClipOff,      /* we won't output out of range samples so don't bother clipping them */
              patestCallback,
              &data );
    if( err != paNoError ) goto error;

    err = Pa_StartStream( stream );
    if( err != paNoError ) goto error;

    printf("Play for %d seconds.\n", NUM_SECONDS );
    Pa_Sleep( NUM_SECONDS * 1000 );

    err = Pa_StopStream( stream );
    if( err != paNoError ) goto error;

    err = Pa_CloseStream( stream );
    if( err != paNoError ) goto error;

    Pa_Terminate();
    printf("Test finished.\n");
    
    return err;
error:
    Pa_Terminate();
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
    fprintf( stderr, "Error number: %d\n", err );
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    return err;
}
예제 #4
0
PaStream *setupAudioStream(PartConvMax *pc)
{
    PaStream *stream;
    PaStreamParameters outputParameters,inputParameters;

    Pa_Initialize();

    //outputParameters.device = Pa_GetDefaultOutputDevice();
    outputParameters.device = 6; //Aggregate Device

    if(outputParameters.device == paNoDevice)
    {
        printf("\nno output device available\n");
        Pa_Terminate();
        exit(-1);
    }

    outputParameters.channelCount = pc->numOutputChannels;
    outputParameters.sampleFormat = paFloat32;
    //outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
    //outputParameters.suggestedLatency = (64.0f / 44100.0f);
    outputParameters.suggestedLatency = ((float)(pc->buffer_size) / 44100.0f);


    //inputParameters.device = Pa_GetDefaultInputDevice();
    inputParameters.device = 6; //Aggregate Device
    if(inputParameters.device == paNoDevice)
    {
        printf("\nno input device available\n");
        Pa_Terminate();
        exit(-1);
    }

    inputParameters.channelCount = pc->numInputChannels;
    inputParameters.sampleFormat = paFloat32;
    inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
    //inputParameters.suggestedLatency = (64.0f / 44100.0f);
    inputParameters.suggestedLatency = ((float)(pc->buffer_size) / 44100.0f);

    PaStreamFlags streamFlags;

    PaMacCoreStreamInfo coreInfo;

    /*This setting is tuned for pro audio apps. It allows SR conversion on input
      and output, but it tries to set the appropriate SR on the device.*/
    //#define paMacCorePro                         (0x01)

    /*This is a setting to minimize CPU usage, even if that means interrupting the device. */
    //#define paMacCoreMinimizeCPU                 (0x0101)
    unsigned long flags = (0x0101);
    PaMacCore_SetupStreamInfo(&coreInfo, flags);
    inputParameters.hostApiSpecificStreamInfo = &coreInfo;
    outputParameters.hostApiSpecificStreamInfo = &coreInfo;

    streamFlags = paNoFlag;


    PaError error = Pa_OpenStream(
            &stream,
            &inputParameters,
            &outputParameters,
            pc->FS,
            pc->buffer_size,
            streamFlags,
            Callback,
            (void*)pc // user data in callback
            );

    if (error) {
        printf("\nError opening stream, error code = %i\n",error);
        printf("%s\n", Pa_GetErrorText(error));
        Pa_Terminate();
        exit(-1);
    }

    const PaStreamInfo* stream_info = Pa_GetStreamInfo(stream);


    printf("\nOutput Stream:\n");
    printf("sample rate: %g \n",stream_info->sampleRate);
    printf("device: %u\n",outputParameters.device);
    printf("channels: %u\n",outputParameters.channelCount);
    printf("suggested latency: %g ms\n", outputParameters.suggestedLatency*1000);
    printf("stream latency: %g ms\n", stream_info->outputLatency*1000);

    printf("\nInput Stream:\n");
    printf("sample rate: %g \n",stream_info->sampleRate);
    printf("device: %u\n",inputParameters.device);
    printf("channels: %u\n",inputParameters.channelCount);
    printf("suggested latency: %g ms\n", inputParameters.suggestedLatency*1000);
    printf("stream latency: %g ms\n", stream_info->inputLatency*1000);

    return stream;
}
예제 #5
0
int main(void)
{
    PaStreamParameters outputParameters;
    PaStream *stream;
    PaError err;
    paTestData data;
#ifdef __APPLE__
    PaMacCoreStreamInfo macInfo;
#endif
    int i;

    /* initialise sinusoidal wavetable */
    for( i=0; i<TABLE_SIZE; i++ )
    {
        data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
    }
    data.left_phase = data.right_phase = 0;

    err = Pa_Initialize();
    if( err != paNoError ) goto error;

    for( i=0; i<2; ++i ) {
        const float sr = i ? SAMPLE_RATE2 : SAMPLE_RATE1;
        printf("PortAudio Test: output sine wave. SR = %g, BufSize = %d\n", sr, FRAMES_PER_BUFFER);
        outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
        if (outputParameters.device == paNoDevice) {
            fprintf(stderr,"Error: No default output device.\n");
            goto error;
        }
        outputParameters.channelCount = 2;       /* stereo output */
        outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
        outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
        /** setup host specific info */
#ifdef __APPLE__
        PaMacCore_SetupStreamInfo( &macInfo, paMacCorePro );
        outputParameters.hostApiSpecificStreamInfo = &macInfo;
#else
        printf( "Hardware SR changing not being tested on this platform.\n" );
        outputParameters.hostApiSpecificStreamInfo = NULL;
#endif
        err = Pa_OpenStream(
                  &stream,
                  NULL, /* no input */
                  &outputParameters,
                  sr,
                  FRAMES_PER_BUFFER,
                  paClipOff,      /* we won't output out of range samples so don't bother clipping them */
                  patestCallback,
                  &data );
       if( err != paNoError ) goto error;

       err = Pa_StartStream( stream );
       if( err != paNoError ) goto error;

       printf("Play for %d seconds.\n", NUM_SECONDS );
       Pa_Sleep( NUM_SECONDS * 1000 );

       err = Pa_StopStream( stream );
       if( err != paNoError ) goto error;

       err = Pa_CloseStream( stream );
       if( err != paNoError ) goto error;
    }

    Pa_Terminate();
    printf("Test finished.\n");
    
    return err;
error:
    Pa_Terminate();
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
    fprintf( stderr, "Error number: %d\n", err );
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    return err;
}