コード例 #1
0
ファイル: bb10_dev.c プロジェクト: KevinHM/pjsip
static void close_play_pcm(struct bb10_stream *stream)
{
    if (stream != NULL && stream->pb_pcm != NULL) {
        snd_pcm_close(stream->pb_pcm);
        stream->pb_pcm = NULL;

        if (stream->pb_audio_manager_handle != 0) {
    	    audio_manager_free_handle(stream->pb_audio_manager_handle);
    	    stream->pb_audio_manager_handle = 0;
        }

        if (stream->pb_ctrl_audio_manager_handle != 0) {
    	    audio_manager_free_handle(stream->pb_ctrl_audio_manager_handle);
    	    stream->pb_ctrl_audio_manager_handle = 0;
        }
    }
}
コード例 #2
0
/**
 * Set up capture based on the audio sample waverec except we use VoIP parameters
 */
static int capture(circular_buffer_t* circular_buffer) {
	// Re-usable buffer for capture
	char *record_buffer;
	record_buffer = (char*) malloc(g_frame_size_c);

	// Some diagnostic variables
	int failed = 0;
	int totalRead = 0;
	snd_pcm_channel_status_t status;
	status.channel = SND_PCM_CHANNEL_CAPTURE;

	// Loop until stopAudio() flags us
	while (g_execute_audio) {
		// This blocking read appears to take much longer than 20ms on the simulator
		// but it never fails and always returns 160 bytes
		int read = snd_pcm_plugin_read(g_pcm_handle_c, record_buffer,
				g_frame_size_c);
		if (read < 0 || read != g_frame_size_c) {
			failed++;
			fprintf(stderr,"CAPTURE FAILURE: snd_pcm_plugin_read: %d requested = %d\n",read,g_frame_size_c);
			if (snd_pcm_plugin_status(g_pcm_handle_c, &status) < 0) {
				fprintf(stderr, "Capture channel status error: %d\n",status.status);
			} else {
				if (status.status == SND_PCM_STATUS_READY
				|| status.status == SND_PCM_STATUS_OVERRUN
				|| status.status == SND_PCM_STATUS_CHANGE
				|| status.status == SND_PCM_STATUS_ERROR) {
					fprintf(stderr, "CAPTURE FAILURE:snd_pcm_plugin_status: = %d \n",status.status);
					if (snd_pcm_plugin_prepare (g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE) < 0) {
						fprintf (stderr, "Capture channel prepare error 1 %d\n",status.status);
						exit (1);
					}

				}
			}
		} else {
			totalRead += read;
			// On simulator always room in the circular buffer
			if (!writeToCircularBuffer(circular_buffer, record_buffer,
					g_frame_size_c)) {
				failed++;
			}
		}
		capture_ready = true;

	}
	fprintf(stderr,"CAPTURE EXIT BEGIN\n");
	(void) snd_pcm_plugin_flush(g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE);
	//(void)snd_mixer_close (mixer_handle);
	(void) snd_pcm_close(g_pcm_handle_c);
	audio_manager_free_handle(g_audio_manager_handle_c);
	// IMPORTANT NB: You only get failed on capture if the play loop has exited hence the circular buffer fills. This is with the simulator
	fprintf(stderr, "CAPTURE EXIT Total Bytes read = %d failed = %d\n",totalRead,failed);
	free(record_buffer);
	return 0;
}
コード例 #3
0
	/**
	 * Set the thread exit flag and cleanup<br>
	 */
void stopPcmAudio() {
	// Threads will see this flag every 20ms in their loop
	fprintf(stderr,"\nStopPCMAudio ****************: ENTER \n");
	g_execute_audio = false;
	fprintf(stderr,"CAPTURE JOIN = %d\n",pthread_join(g_capturethread, NULL));
	fprintf(stderr,"PLAY JOIN = %d\n",pthread_join(g_playerthread, NULL));
	audio_manager_free_handle(g_audio_manager_handle_t);
	destroyCircularBuffer(g_circular_buffer);
	fprintf(stderr,"StopPCMAudio ****************: EXIT\n");
}
コード例 #4
0
void AudioControl::releaseAudioManagerHandle()
{
	if(m_dtmfAudioManager != 0){
		int ret = audio_manager_free_handle(m_dtmfAudioManager);
		if(ret != 0){
			qDebug() << "AudioControl::releaseHandle() = " << ret;
		}
		m_dtmfAudioManager = 0;
	}
}
コード例 #5
0
ファイル: bb10_dev.c プロジェクト: KevinHM/pjsip
static void close_capture_pcm(struct bb10_stream *stream)
{
    if (stream != NULL && stream->ca_pcm != NULL) {
        snd_pcm_close(stream->ca_pcm);
        stream->ca_pcm = NULL;

        if (stream->ca_audio_manager_handle != 0) {
    	    audio_manager_free_handle(stream->ca_audio_manager_handle);
    	    stream->ca_audio_manager_handle = 0;
        }
    }
}
コード例 #6
0
void cleanupToneGenerator()
{
    int i;

    if( live == STOPPED ) {
        return;
    }
    pthread_mutex_lock( &toneMutex );

    live = STOPPED;

    // Terminate all playbacks
    Tone *tone = NULL;
    for(tone = tones; tone != NULL; tone = tone->next ) {
        tone->active = false;
    }

    pthread_mutex_unlock( &toneMutex );
    pthread_cond_signal( &condvar_newtone );

    pthread_join( toneGeneratorThread, NULL );
    snd_pcm_close (playback_handle);

    //free( frag_buffer );

    if( audioman_handle ) {
        audio_manager_free_handle( audioman_handle );
    }

    pthread_cond_destroy( &condvar_newtone );

    pthread_mutex_destroy( &toneMutex );

    pthread_mutex_destroy (&fillMutex);

	free(record_buffer);
	free(render_buffer);
	free(stage_samples);
	free(stage_buffer);
}
コード例 #7
0
static int voice_test()
{
    int rtn = 0;
    char* name;
    fd_set rfds, wfds;
    Audio_t hPcm_Mic;
    Audio_t hPcm_Spk;
    snd_pcm_channel_params_t params;
    bool bQuit = false;

    /************************ CAPTURE **************************/

    //  configuring capture (mic)
    name = "voice";

    //  get audioman handle
    rtn = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, getpid(), (bool)false, &hPcm_Mic.hAudioman);
    if(rtn < 0) {
        cli_print("audio_manager_get_handle (mic) failed %s", strerror(-rtn));
        return -1;
     }

    cli_print("Opening %s - for capture", name);
    rtn = snd_pcm_open_name(&hPcm_Mic.pDs, name, SND_PCM_OPEN_CAPTURE);
    if (rtn < 0) {
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        cli_print("snd_pcm_open_name (mic) failed %s", snd_strerror(rtn));
        return -1; // snd_pcm calls return negative values; make positive
    }

    rtn = snd_pcm_set_audioman_handle(hPcm_Mic.pDs, hPcm_Mic.hAudioman);
    if (rtn < 0) {
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        cli_print("snd_pcm_set_audioman_handle (mic) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        return -1;
    }

    // disable mmap
    (void)snd_pcm_plugin_set_disable(hPcm_Mic.pDs, (unsigned int)PLUGIN_DISABLE_MMAP);

    // set parameters
    memset(&params, 0, sizeof(params));
    params.mode = SND_PCM_MODE_BLOCK;
    params.channel = SND_PCM_CHANNEL_CAPTURE;
    params.start_mode = SND_PCM_START_GO;
    params.stop_mode = SND_PCM_STOP_ROLLOVER;
    params.buf.block.frag_size = fragsize;
    params.buf.block.frags_max = 1;
    params.buf.block.frags_min = 1;
    params.format.rate = 8000; //samplerate;
    params.format.interleave = 1;
    params.format.voices = channels;
    params.format.format = SND_PCM_SFMT_S16_LE;

    rtn = snd_pcm_plugin_params(hPcm_Mic.pDs, &params);
    if (rtn < 0) {
        cli_print("snd_pcm_plugin_params (mic) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        return -1;
    }

    // get file descriptor for use with the select() call
    hPcm_Mic.hFD = snd_pcm_file_descriptor(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE);
    if (hPcm_Mic.hFD < 0) {
        cli_print("snd_pcm_file_descriptor (mic) failed %s", snd_strerror(hPcm_Mic.hFD));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        return -1;
    }
    // Signal the driver to ready the capture channel
    rtn = snd_pcm_plugin_prepare(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE);
    if (rtn < 0) {
        cli_print("snd_pcm_plugin_prepare (mic) failed %s", snd_strerror(errno));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        return -1;
    }
    fragsize = params.buf.block.frag_size;


    /************************ PLAYBACK **************************/

    name = "voice";

    // get and set audioman handle
    rtn = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, getpid(), (bool)false, &hPcm_Spk.hAudioman);
    if (rtn < 0) {
        cli_print("audioman audio_manager_get_handle (spk) failed %s", strerror(-rtn) );
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        return -1;
    }
#ifdef HANDSET
    // set audio manager handle type
    rtn = audio_manager_set_handle_type(hPcm_Spk.hAudioman, AUDIO_TYPE_VIDEO_CHAT, device_type, device_type);
    if (rtn < 0) {
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        cli_print("audio_manager_set_handle_type (spk) failed %s", strerror(-rtn));
        return -1;
    }
#endif
    // Create a handle and open a connection to an audio interface specified by name
    cli_print("Opening %s - for playback", name);
    rtn = snd_pcm_open_name(&hPcm_Spk.pDs, name, SND_PCM_OPEN_PLAYBACK);
    if (rtn < 0) {
        cli_print("snd_pcm_open_name (spk) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }
    rtn = snd_pcm_set_audioman_handle(hPcm_Spk.pDs, hPcm_Spk.hAudioman);
    if (rtn < 0) {
        cli_print("snd_pcm_set_audioman_handle (spk) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)snd_pcm_close(hPcm_Spk.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }

    // disable mmap
    (void)snd_pcm_plugin_set_disable(hPcm_Spk.pDs, (unsigned int)PLUGIN_DISABLE_MMAP);

    // set parameters
    memset(&params, 0, sizeof(params));
    params.mode = SND_PCM_MODE_BLOCK;
    params.channel = SND_PCM_CHANNEL_PLAYBACK;
    params.start_mode = SND_PCM_START_GO;
    params.stop_mode = SND_PCM_STOP_ROLLOVER;
    params.buf.block.frag_size = fragsize;
    params.buf.block.frags_max = 1;
    params.buf.block.frags_min = 1;
    params.format.rate = samplerate;
    params.format.interleave = 1;
    params.format.voices = channels;
    params.format.format = SND_PCM_SFMT_S16_LE;

    // Set the configurable parameters for a PCM channel
    rtn = snd_pcm_plugin_params(hPcm_Spk.pDs, &params);
    if (rtn < 0) {
        cli_print("snd_pcm_plugin_params  (spk) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)snd_pcm_close(hPcm_Spk.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }

    // get file descriptor for use with the select() call
    hPcm_Spk.hFD = snd_pcm_file_descriptor(hPcm_Spk.pDs, SND_PCM_CHANNEL_PLAYBACK);
    if (hPcm_Spk.hFD < 0) {
        cli_print("snd_pcm_file_descriptor (spk) failed %s", snd_strerror(hPcm_Spk.hFD));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)snd_pcm_close(hPcm_Spk.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }
    // Signal the driver to ready the playback channel
    rtn = snd_pcm_plugin_prepare(hPcm_Spk.pDs, SND_PCM_CHANNEL_PLAYBACK);
    if (rtn < 0) {
        cli_print("snd_pcm_plugin_prepare  (spk) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)snd_pcm_close(hPcm_Spk.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }
    fragsize = params.buf.block.frag_size;

    rtn = snd_pcm_capture_go(hPcm_Mic.pDs);
    if( rtn < 0) {
        cli_print("snd_pcm_capture_go (mic) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)snd_pcm_close(hPcm_Spk.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }
    rtn = snd_pcm_playback_go(hPcm_Spk.pDs);
    if (rtn < 0) {
        cli_print("snd_pcm_playback_go (spk) failed %s", snd_strerror(rtn));
        (void)snd_pcm_close(hPcm_Mic.pDs);
        (void)snd_pcm_close(hPcm_Spk.pDs);
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
        return -1;
    }

    /******************* PLAYBACK/RECORD LOOP **************************/
    while(!bQuit)
    {
        int width;
        struct timeval timeout;
        timeout.tv_sec = 0;
        timeout.tv_usec = 350000; // 350 ms

        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        FD_SET(hPcm_Mic.hFD, &rfds);
        FD_SET(hPcm_Spk.hFD, &wfds);

        width = ((hPcm_Spk.hFD > hPcm_Mic.hFD) ? hPcm_Spk.hFD : hPcm_Mic.hFD) + 1;
        rtn = select(width, &rfds, &wfds, NULL, &timeout);
        if (rtn > 0) {
            if (FD_ISSET(hPcm_Spk.hFD, &wfds)) {
                bQuit = process_write(hPcm_Spk.pDs);
            }
            if (FD_ISSET(hPcm_Mic.hFD, &rfds)) {
                bQuit = process_read(hPcm_Mic.pDs);
            }
        }
        else if (rtn == 0){
            cli_print("select: timed out");
            bQuit = true;
        }
        else { // (rtn < 0)
            cli_print("select: %s", strerror(errno));
            bQuit = true;
        }
    }

    // Ensure audio processing is stopped
    if ((rtn = snd_pcm_plugin_playback_drain(hPcm_Spk.pDs)) < 0) {
        cli_print("snd_pcm_plugin_playback_drain (spk) failed %s", snd_strerror(rtn));
    }
    if ((rtn = snd_pcm_plugin_flush(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE)) < 0) {
        cli_print("snd_pcm_plugin_flush (mic) failed %s", snd_strerror(rtn));
    }
    if ((rtn = snd_pcm_close(hPcm_Spk.pDs)) < 0) {
        cli_print("snd_pcm_close (spk) failed %s", snd_strerror(rtn));
    }
    if ((rtn = snd_pcm_close(hPcm_Mic.pDs)) < 0) {
        cli_print("snd_pcm_close (mic) failed %s", snd_strerror(rtn));
    }
    if (hPcm_Spk.hAudioman) {
        (void)audio_manager_free_handle(hPcm_Spk.hAudioman);
    }
    if (hPcm_Mic.hAudioman) {
        (void)audio_manager_free_handle(hPcm_Mic.hAudioman);
    }
    return 0;
}
コード例 #8
0
ファイル: bb10_dev.c プロジェクト: KevinHM/pjsip
/*
 * BB10 - tests loads the audio units and sets up the driver structure
 */
static pj_status_t bb10_add_dev (struct bb10_factory *af)
{
    pjmedia_aud_dev_info *adi;
    int pb_result, ca_result;
    unsigned int handle;
    snd_pcm_t *pcm_handle;

    if (af->dev_cnt >= PJ_ARRAY_SIZE(af->devs))
        return PJ_ETOOMANY;

    adi = &af->devs[af->dev_cnt];

    TRACE_((THIS_FILE, "bb10_add_dev Enter"));

    if ((pb_result = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT,
                                                     &pcm_handle,
                                                     &handle,
                                                     (char*)"voice",
                                                     SND_PCM_OPEN_PLAYBACK))
                                                     >= 0)
    {
	snd_pcm_close (pcm_handle);
	audio_manager_free_handle(handle);
    } else {
        TRACE_((THIS_FILE, "Try to open the device for playback - failure"));
    }

    if ((ca_result = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT,
                                                     &pcm_handle,
                                                     &handle,
                                                     (char*)"voice",
                                                     SND_PCM_OPEN_CAPTURE))
                                                     >= 0)
    {
	snd_pcm_close (pcm_handle);
	audio_manager_free_handle(handle);

    } else {
        TRACE_((THIS_FILE, "Try to open the device for capture - failure"));
    }

    if (pb_result < 0 && ca_result < 0) {
        TRACE_((THIS_FILE, "Unable to open sound device", "preferred"));
        return PJMEDIA_EAUD_NODEV;
    }

    /* Reset device info */
    pj_bzero(adi, sizeof(*adi));

    /* Set device name */
    strcpy(adi->name, "preferred");

    /* Check the number of playback channels */
    adi->output_count = (pb_result >= 0) ? 1 : 0;

    /* Check the number of capture channels */
    adi->input_count = (ca_result >= 0) ? 1 : 0;

    /* Set the default sample rate */
    adi->default_samples_per_sec = 8000;

    /* Driver name */
    strcpy(adi->driver, "BB10");

    ++af->dev_cnt;

    PJ_LOG (4,(THIS_FILE, "Added sound device %s", adi->name));

    return PJ_SUCCESS;
}
コード例 #9
0
/**
 * setup play based on the audio sample wave
 */
static int play(circular_buffer_t* circular_buffer) {

	// If there's nothing in the circular buffer play the sound of silence
	// In the real world you may well play the last frame you received. There are algorithms DSP experts know about apparently
	char* silence_buffer = (char*) malloc(g_frame_size_p);
	memset(silence_buffer, SILENCE, g_frame_size_p);

	// Data read from the circular buffer
	char* play_buffer = (char*) malloc(g_frame_size_p);
	memset(play_buffer, 0, g_frame_size_p);

	// Diagnostics
	int total_written = 0;
	int failed = 0;
	int capture_not_ready = 0;
	// Loop till stopAudio() flags us
	while (g_execute_audio) {
		int written;
		// Read the circular buffer
		// returns true only if there is data to satisfy frame_size
		if (!capture_ready) {
			++capture_not_ready;
			written = snd_pcm_plugin_write(g_pcm_handle_p, play_buffer,
					g_frame_size_p);
			if (written < 0 || written != g_frame_size_p) {
				fprintf(stderr,"PLAY RESET 1\n");
				resetPlay();
			}else{
				total_written += written;
			}

		} else if (readFromCircularBuffer(circular_buffer, play_buffer,
				g_frame_size_p)) {
			written = snd_pcm_plugin_write(g_pcm_handle_p, play_buffer,
					g_frame_size_p);
			if (written < 0 || written != g_frame_size_p) {
				fprintf(stderr,"PLAY RESET 2\n");
				resetPlay();
			}else{
				total_written += written;
			}

		} else {
			// You would expect the jitter buffer to be possibly empty at startup because threads are not synchronized
			// increasing the frags_max reduces the occurrences of failure here
			// On the simulator it always fails written = 0 presumably meaning an overrun
			written = snd_pcm_plugin_write(g_pcm_handle_p, silence_buffer,
					g_frame_size_p);
			if (written < 0 || written != g_frame_size_p) {
				fprintf(stderr,"PLAY RESET 3\n");
				resetPlay();
			}
			failed++;
		}
	}
	fprintf(stderr,"PLAY EXIT BEGIN\n");
	(void) snd_pcm_plugin_flush(g_pcm_handle_p, SND_PCM_CHANNEL_PLAYBACK);
	(void) snd_pcm_close(g_pcm_handle_p);
	audio_manager_free_handle(g_audio_manager_handle_p);
	free(play_buffer);
	free(silence_buffer);
	fprintf(stderr,"PLAY EXIT Total Bytes written = %d failed = %d capture_not_ready %d\n",total_written,failed,capture_not_ready);
	return 0;
}
コード例 #10
0
int initToneGenerator(void)
{
    _int32 staticMemSize, scratchMemSize;
    int policy;
    struct sched_param param;
    int error;
    pthread_attr_t attr;

    if( live == RUNNING) {
        return 0;
    } else if( live == DEAD ) {
        return -EINVAL;
    }


   if( (error = pthread_mutex_init (&fillMutex, NULL) ) != 0 ) {
		return error;
	}

    tone_count = 0;
    if( (error = pthread_mutex_init( &toneMutex, NULL ) ) != 0 ) {
        return error;
    }

    if( (error = pthread_cond_init( &condvar_newtone, NULL ) ) != 0 ) {
        pthread_mutex_destroy( &toneMutex );
        return error;
    }

    audio_manager_get_handle( AUDIO_TYPE_VOICE_TONES, getpid(), true, &audioman_handle );

    if( (error = setupAudio( )) != 0 ) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to initialize audio %s\n", snd_strerror(error));
        pthread_mutex_destroy( &toneMutex );
        pthread_cond_destroy( &condvar_newtone );
        if( audioman_handle ) {
            audio_manager_free_handle( audioman_handle );
        }
        return error;
    }

	// Re-usable buffer for generation
	stage_buffer = malloc (frame_size);
	memset(stage_buffer, 0, frame_size);
	stage_samples = malloc (frame_size);
	memset(stage_samples, 0, frame_size);
	record_buffer = malloc (frame_size);
	memset(record_buffer, 0, frame_size);
	render_buffer = malloc (frame_size);
	memset(render_buffer, 0, frame_size);

    // Default tonegen volume is 75% to achieve a 16dB loss ( SW mixer uses 10%=6dB. )
    setVolume(85);

    live = RUNNING;

    pthread_attr_init (&attr);
    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
    pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);
    pthread_getschedparam (pthread_self (), &policy, &param);
    param.sched_priority=12;
    pthread_attr_setschedparam (&attr, &param);
    pthread_attr_setschedpolicy (&attr, SCHED_RR);

    if( (error = pthread_create( &toneGeneratorThread, &attr, processTones, NULL ) ) != 0 ) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to create tone thread %s\n", strerror(error));
        snd_pcm_close (playback_handle);
        //free( frag_buffer );
        pthread_mutex_destroy( &toneMutex );
        pthread_cond_destroy( &condvar_newtone );

        live = STOPPED;
        if( audioman_handle ) {
            audio_manager_free_handle( audioman_handle );
        }
        pthread_attr_destroy(&attr);
        return error;
    }

    pthread_attr_destroy(&attr);

    return 0;
}