Пример #1
0
	void OpenAudio()
	{
		int card = -1, dev = 0;

		snd_pcm_channel_info_t pi;
		snd_mixer_group_t group;
		snd_pcm_channel_params_t pp;
		snd_pcm_channel_setup_t setup;

		mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES;
		mixbuf = (uint8_t*)malloc(mixlen);
		if (mixbuf == NULL)
			return;
		memset(mixbuf, 0, mixlen);

		if ((snd_pcm_open_preferred(&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0)
			return;

		memset(&pi, 0, sizeof (pi));
		pi.channel = SND_PCM_CHANNEL_PLAYBACK;
		if ((snd_pcm_plugin_info (pcm_handle, &pi)) < 0)
			return;

		memset(&pp, 0, sizeof (pp));
		pp.mode = SND_PCM_MODE_BLOCK;
		pp.channel = SND_PCM_CHANNEL_PLAYBACK;
		pp.start_mode = SND_PCM_START_FULL;
		pp.stop_mode = SND_PCM_STOP_STOP;

		pp.buf.block.frag_size = pi.max_fragment_size;
		pp.buf.block.frags_max = -1;
		pp.buf.block.frags_min = 1;

		pp.format.interleave = 1;
		pp.format.rate = AUDIO_FREQ;
		pp.format.voices = AUDIO_CHANNELS;
		pp.format.format = SND_PCM_SFMT_S16_LE;

		if ((snd_pcm_plugin_params (pcm_handle, &pp)) < 0)
			return;

		snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);

		memset (&setup, 0, sizeof(setup));
		memset (&group, 0, sizeof(group));
		setup.channel = SND_PCM_CHANNEL_PLAYBACK;
		setup.mixer_gid = &group.gid;
		if ((snd_pcm_plugin_setup (pcm_handle, &setup)) < 0)
			return;
		setup.buf.block.frag_size;
		if ((snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0)
			return;
		pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
		pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this);
	}
Пример #2
0
static void qsa_start_capture(ALCdevice* device)
{
    qsa_data* data=(qsa_data*)device->ExtraData;
    int rstatus;

    if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
    {
        ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
        return;
    }

    memset(&data->csetup, 0, sizeof(data->csetup));
    data->csetup.channel=SND_PCM_CHANNEL_CAPTURE;
    if ((rstatus=snd_pcm_plugin_setup(data->pcmHandle, &data->csetup))<0)
    {
        ERR("capture setup failed: %s\n", snd_strerror(rstatus));
        return;
    }

    snd_pcm_capture_go(data->pcmHandle);
}
static void playsetup() {

	snd_pcm_channel_setup_t setup;
	//Enabling Echo canceller
	int ret;
	snd_pcm_channel_info_t pi;
	snd_mixer_group_t group;
	snd_pcm_channel_params_t pp;

	//audio routing enabled with AEC
	if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT,
			&g_pcm_handle_p, &g_audio_manager_handle_p, (char*) "voice",
			SND_PCM_OPEN_PLAYBACK)) < 0) {
		return;
	}

	snd_pcm_plugin_set_disable(g_pcm_handle_p, PLUGIN_DISABLE_MMAP);
    snd_pcm_plugin_set_enable(g_pcm_handle_p, PLUGIN_ROUTING);


	memset(&pi, 0, sizeof(pi));
	pi.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((ret = snd_pcm_plugin_info(g_pcm_handle_p, &pi)) < 0) {
		fprintf(stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (ret));
		return;
	}

	fprintf(stderr,"PLAY Minimum Rate = %d\n",pi.min_rate);
	// Interestingly on the simulator this returns 4096 but in reality always 170 is the result
	fprintf(stderr,"PLAY Minimum fragment size = %d\n",pi.min_fragment_size);

	memset(&pp, 0, sizeof(pp));

	// Request VoIP compatible capabilities
	// On simulator frag_size is always negotiated to 170
	pp.mode = SND_PCM_MODE_BLOCK;
	pp.channel = SND_PCM_CHANNEL_PLAYBACK;
	//pp.start_mode = SND_PCM_START_DATA;
	pp.stop_mode = SND_PCM_STOP_ROLLOVER;
	pp.start_mode = SND_PCM_START_FULL;
	pp.buf.block.frag_size = PREFERRED_FRAME_SIZE;
	// Increasing this internal buffer count delays write failure in the loop
	pp.buf.block.frags_max = 5;
	pp.buf.block.frags_min = 1;
	pp.format.interleave = 1;
	pp.format.rate = VOIP_SAMPLE_RATE;
	pp.format.voices = 1;
	pp.format.format = SND_PCM_SFMT_S16_LE;




	// Make the calls as per the wave sample
	if ((ret = snd_pcm_plugin_params(g_pcm_handle_p, &pp)) < 0) {
		fprintf(stderr, "pb snd_pcm_plugin_params failed: %s\n", snd_strerror (ret));
		return;
	}

	memset(&setup, 0, sizeof(setup));
	memset(&group, 0, sizeof(group));
	setup.channel = SND_PCM_CHANNEL_PLAYBACK;
	setup.mixer_gid = &group.gid;
	if ((ret = snd_pcm_plugin_setup(g_pcm_handle_p, &setup)) < 0) {
		fprintf(stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (ret));
		return;
	}

	fprintf(stderr,"PLAY frame_size %d \n", setup.buf.block.frag_size);
	fprintf(stderr,"PLAY Rate %d \n", setup.format.rate);
	g_frame_size_p = setup.buf.block.frag_size;

	if (group.gid.name[0] == 0) {
		fprintf(stderr,"FATAL Mixer Pcm Group [%s] Not Set \n", group.gid.name);
		exit (-1);
	}
	printf("Mixer Pcm Group [%s]\n", group.gid.name);
	if ((ret = snd_pcm_plugin_prepare(g_pcm_handle_p, SND_PCM_CHANNEL_PLAYBACK))
			< 0) {
		fprintf(stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (ret));
	}
}
static void capturesetup() {

	snd_pcm_channel_setup_t setup;
	int ret;
	snd_pcm_channel_info_t pi;
	snd_mixer_group_t group;
	snd_pcm_channel_params_t pp;
	int card = setup.mixer_card;


	if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, &g_pcm_handle_c,
			&g_audio_manager_handle_c, (char*) "voice", SND_PCM_OPEN_CAPTURE)) < 0) {

		return;
	}

	snd_pcm_plugin_set_disable(g_pcm_handle_c, PLUGIN_DISABLE_MMAP);
	snd_pcm_plugin_set_enable(g_pcm_handle_c, PLUGIN_ROUTING);

	// sample reads the capabilities of the capture
	memset(&pi, 0, sizeof(pi));
	pi.channel = SND_PCM_CHANNEL_CAPTURE;
	if ((ret = snd_pcm_plugin_info(g_pcm_handle_c, &pi)) < 0) {
		fprintf(stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (ret));
		return;
	}

	fprintf(stderr,"CAPTURE Minimum Rate = %d\n",pi.min_rate);

	// Request the VoIP parameters
	// These parameters are different to waverec sample
	memset(&pp, 0, sizeof(pp));
	fprintf(stderr,"CAPTURE Minimum fragment size = %d\n",pi.min_fragment_size);
	// Blocking read
	pp.mode = SND_PCM_MODE_BLOCK;
	pp.channel = SND_PCM_CHANNEL_CAPTURE;
	//pp.start_mode = SND_PCM_START_DATA;
	// Auto-recover from errors
	pp.stop_mode = SND_PCM_STOP_ROLLOVER;
	pp.start_mode = SND_PCM_START_DATA;
	pp.buf.block.frag_size = PREFERRED_FRAME_SIZE;
	pp.buf.block.frags_max = 3;
	pp.buf.block.frags_min = 1;
	pp.format.interleave = 1;
	pp.format.rate = VOIP_SAMPLE_RATE;
	pp.format.voices = 1;
	pp.format.format = SND_PCM_SFMT_S16_LE;
	// make the request
	if ((ret = snd_pcm_plugin_params(g_pcm_handle_c, &pp)) < 0) {
		fprintf(stderr, "ca snd_pcm_plugin_params failed: %s\n", snd_strerror (ret));
		return;
	}

	// Again based on the sample
	memset(&setup, 0, sizeof(setup));
	memset(&group, 0, sizeof(group));
	setup.channel = SND_PCM_CHANNEL_CAPTURE;
	setup.mixer_gid = &group.gid;
	if ((ret = snd_pcm_plugin_setup(g_pcm_handle_c, &setup)) < 0) {
		fprintf(stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (ret));
		return;
	}
	// On the simulator at least, our requested capabilities are accepted.
	fprintf(stderr,"CAPTURE Format %s card = %d\n", snd_pcm_get_format_name (setup.format.format),card);
	fprintf(stderr,"CAPTURE Rate %d \n", setup.format.rate);
	g_frame_size_c = setup.buf.block.frag_size;

	if (group.gid.name[0] == 0) {
		printf("Mixer Pcm Group [%s] Not Set \n", group.gid.name);
		printf("***>>>> Input Gain Controls Disabled <<<<*** \n");
	} else {
		printf("Mixer Pcm Group [%s]\n", group.gid.name);
	}


	g_frame_size_c = setup.buf.block.frag_size;
	fprintf(stderr, "CAPTURE frame_size = %d\n", g_frame_size_c);

	// Sample calls prepare()
	if ((ret = snd_pcm_plugin_prepare(g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE))
			< 0) {
		fprintf(stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (ret));
	}
}
Пример #5
0
static int
QSA_OpenDevice(_THIS, const char *devname, int iscapture)
{
    int status = 0;
    int format = 0;
    SDL_AudioFormat test_format = 0;
    int found = 0;
    snd_pcm_channel_setup_t csetup;
    snd_pcm_channel_params_t cparams;

    /* Initialize all variables that we clean on shutdown */
    this->hidden =
        (struct SDL_PrivateAudioData *) SDL_calloc(1,
                                                   (sizeof
                                                    (struct
                                                     SDL_PrivateAudioData)));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));

    /* Initialize channel transfer parameters to default */
    QSA_InitAudioParams(&cparams);

    /* Initialize channel direction: capture or playback */
    this->hidden->iscapture = iscapture;

    /* Find deviceid and cardid by device name for playback */
    if ((!this->hidden->iscapture) && (devname != NULL)) {
        uint32_t device;
        int32_t status;

        /* Search in the playback devices */
        device = 0;
        do {
            status = SDL_strcmp(qsa_playback_device[device].name, devname);
            if (status == 0) {
                /* Found requested device */
                this->hidden->deviceno = qsa_playback_device[device].deviceno;
                this->hidden->cardno = qsa_playback_device[device].cardno;
                break;
            }
            device++;
            if (device >= qsa_playback_devices) {
                QSA_CloseDevice(this);
                return SDL_SetError("No such playback device");
            }
        } while (1);
    }

    /* Find deviceid and cardid by device name for capture */
    if ((this->hidden->iscapture) && (devname != NULL)) {
        /* Search in the capture devices */
        uint32_t device;
        int32_t status;

        /* Searching in the playback devices */
        device = 0;
        do {
            status = SDL_strcmp(qsa_capture_device[device].name, devname);
            if (status == 0) {
                /* Found requested device */
                this->hidden->deviceno = qsa_capture_device[device].deviceno;
                this->hidden->cardno = qsa_capture_device[device].cardno;
                break;
            }
            device++;
            if (device >= qsa_capture_devices) {
                QSA_CloseDevice(this);
                return SDL_SetError("No such capture device");
            }
        } while (1);
    }

    /* Check if SDL requested default audio device */
    if (devname == NULL) {
        /* Open system default audio device */
        if (!this->hidden->iscapture) {
            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
                                            &this->hidden->cardno,
                                            &this->hidden->deviceno,
                                            SND_PCM_OPEN_PLAYBACK);
        } else {
            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
                                            &this->hidden->cardno,
                                            &this->hidden->deviceno,
                                            SND_PCM_OPEN_CAPTURE);
        }
    } else {
        /* Open requested audio device */
        if (!this->hidden->iscapture) {
            status =
                snd_pcm_open(&this->hidden->audio_handle,
                             this->hidden->cardno, this->hidden->deviceno,
                             SND_PCM_OPEN_PLAYBACK);
        } else {
            status =
                snd_pcm_open(&this->hidden->audio_handle,
                             this->hidden->cardno, this->hidden->deviceno,
                             SND_PCM_OPEN_CAPTURE);
        }
    }

    /* Check if requested device is opened */
    if (status < 0) {
        this->hidden->audio_handle = NULL;
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_open", status);
    }

    if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
        /* Disable QSA MMAP plugin for buggy audio drivers */
        status =
            snd_pcm_plugin_set_disable(this->hidden->audio_handle,
                                       PLUGIN_DISABLE_MMAP);
        if (status < 0) {
            QSA_CloseDevice(this);
            return QSA_SetError("snd_pcm_plugin_set_disable", status);
        }
    }

    /* Try for a closest match on audio format */
    format = 0;
    /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
    found = 0;

    for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
        /* if match found set format to equivalent QSA format */
        switch (test_format) {
        case AUDIO_U8:
            {
                format = SND_PCM_SFMT_U8;
                found = 1;
            }
            break;
        case AUDIO_S8:
            {
                format = SND_PCM_SFMT_S8;
                found = 1;
            }
            break;
        case AUDIO_S16LSB:
            {
                format = SND_PCM_SFMT_S16_LE;
                found = 1;
            }
            break;
        case AUDIO_S16MSB:
            {
                format = SND_PCM_SFMT_S16_BE;
                found = 1;
            }
            break;
        case AUDIO_U16LSB:
            {
                format = SND_PCM_SFMT_U16_LE;
                found = 1;
            }
            break;
        case AUDIO_U16MSB:
            {
                format = SND_PCM_SFMT_U16_BE;
                found = 1;
            }
            break;
        case AUDIO_S32LSB:
            {
                format = SND_PCM_SFMT_S32_LE;
                found = 1;
            }
            break;
        case AUDIO_S32MSB:
            {
                format = SND_PCM_SFMT_S32_BE;
                found = 1;
            }
            break;
        case AUDIO_F32LSB:
            {
                format = SND_PCM_SFMT_FLOAT_LE;
                found = 1;
            }
            break;
        case AUDIO_F32MSB:
            {
                format = SND_PCM_SFMT_FLOAT_BE;
                found = 1;
            }
            break;
        default:
            {
                break;
            }
        }

        if (!found) {
            test_format = SDL_NextAudioFormat();
        }
    }

    /* assumes test_format not 0 on success */
    if (test_format == 0) {
        QSA_CloseDevice(this);
        return SDL_SetError("QSA: Couldn't find any hardware audio formats");
    }

    this->spec.format = test_format;

    /* Set the audio format */
    cparams.format.format = format;

    /* Set mono/stereo/4ch/6ch/8ch audio */
    cparams.format.voices = this->spec.channels;

    /* Set rate */
    cparams.format.rate = this->spec.freq;

    /* Setup the transfer parameters according to cparams */
    status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
    if (status < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_channel_params", status);
    }

    /* Make sure channel is setup right one last time */
    SDL_memset(&csetup, 0, sizeof(csetup));
    if (!this->hidden->iscapture) {
        csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    } else {
        csetup.channel = SND_PCM_CHANNEL_CAPTURE;
    }

    /* Setup an audio channel */
    if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
        QSA_CloseDevice(this);
        return SDL_SetError("QSA: Unable to setup channel");
    }

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    this->hidden->pcm_len = this->spec.size;

    if (this->hidden->pcm_len == 0) {
        this->hidden->pcm_len =
            csetup.buf.block.frag_size * this->spec.channels *
            (snd_pcm_format_width(format) / 8);
    }

    /*
     * Allocate memory to the audio buffer and initialize with silence
     *  (Note that buffer size must be a multiple of fragment size, so find
     *  closest multiple)
     */
    this->hidden->pcm_buf =
        (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
    if (this->hidden->pcm_buf == NULL) {
        QSA_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->pcm_buf, this->spec.silence,
               this->hidden->pcm_len);

    /* get the file descriptor */
    if (!this->hidden->iscapture) {
        this->hidden->audio_fd =
            snd_pcm_file_descriptor(this->hidden->audio_handle,
                                    SND_PCM_CHANNEL_PLAYBACK);
    } else {
        this->hidden->audio_fd =
            snd_pcm_file_descriptor(this->hidden->audio_handle,
                                    SND_PCM_CHANNEL_CAPTURE);
    }

    if (this->hidden->audio_fd < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_file_descriptor", status);
    }

    /* Prepare an audio channel */
    if (!this->hidden->iscapture) {
        /* Prepare audio playback */
        status =
            snd_pcm_plugin_prepare(this->hidden->audio_handle,
                                   SND_PCM_CHANNEL_PLAYBACK);
    } else {
        /* Prepare audio capture */
        status =
            snd_pcm_plugin_prepare(this->hidden->audio_handle,
                                   SND_PCM_CHANNEL_CAPTURE);
    }

    if (status < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_plugin_prepare", status);
    }

    /* We're really ready to rock and roll. :-) */
    return 0;
}
Пример #6
0
static int NTO_OpenAudio(_THIS, SDL_AudioSpec* spec)
{
    int rval;
    int format;
    Uint16 test_format;
    int found;

    audio_handle = NULL;
    this->enabled = 0;

    if (pcm_buf != NULL)
    {
        SDL_FreeAudioMem(pcm_buf); 
        pcm_buf = NULL;
    }

    /* initialize channel transfer parameters to default */
    NTO_InitAudioParams(&cparams);

    /* Open the audio device */
    rval = snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS);
    if (rval < 0)
    {
        SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", snd_strerror(rval));
        return (-1);
    }

    if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND))
    {
        /* enable count status parameter */
        if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP)) < 0)
        {
            SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval));
            return (-1);
        }
    }

    /* Try for a closest match on audio format */
    format = 0;
    /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */
    found = 0;

    for (test_format=SDL_FirstAudioFormat(spec->format); !found ;)
    {
        /* if match found set format to equivalent ALSA format */
        switch (test_format)
        {
            case AUDIO_U8:
                           format = SND_PCM_SFMT_U8;
                           found = 1;
                           break;
            case AUDIO_S8:
                           format = SND_PCM_SFMT_S8;
                           found = 1;
                           break;
            case AUDIO_S16LSB:
                           format = SND_PCM_SFMT_S16_LE;
                           found = 1;
                           break;
            case AUDIO_S16MSB:
                           format = SND_PCM_SFMT_S16_BE;
                           found = 1;
                           break;
            case AUDIO_U16LSB:
                           format = SND_PCM_SFMT_U16_LE;
                           found = 1;
                           break;
            case AUDIO_U16MSB:
                           format = SND_PCM_SFMT_U16_BE;
                           found = 1;
                           break;
            default:
                           break;
        }

        if (!found)
        {
            test_format = SDL_NextAudioFormat();
        }
    }

    /* assumes test_format not 0 on success */
    if (test_format == 0)
    {
        SDL_SetError("NTO_OpenAudio(): Couldn't find any hardware audio formats");
        return (-1);
    }

    spec->format = test_format;

    /* Set the audio format */
    cparams.format.format = format;

    /* Set mono or stereo audio (currently only two channels supported) */
    cparams.format.voices = spec->channels;
	
    /* Set rate */
    cparams.format.rate = spec->freq;

    /* Setup the transfer parameters according to cparams */
    rval = snd_pcm_plugin_params(audio_handle, &cparams);
    if (rval < 0)
    {
        SDL_SetError("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", snd_strerror(rval));
        return (-1);
    }

    /* Make sure channel is setup right one last time */
    SDL_memset(&csetup, 0x00, sizeof(csetup));
    csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0)
    {
        SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n");
        return -1;
    }


    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(spec);

    pcm_len = spec->size;

    if (pcm_len==0)
    {
        pcm_len = csetup.buf.block.frag_size * spec->channels * (snd_pcm_format_width(format)/8);
    }

    /* Allocate memory to the audio buffer and initialize with silence (Note that
       buffer size must be a multiple of fragment size, so find closest multiple)
    */
    pcm_buf = (Uint8*)SDL_AllocAudioMem(pcm_len);
    if (pcm_buf == NULL)
    {
        SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n");
        return (-1);
    }
    SDL_memset(pcm_buf, spec->silence, pcm_len);

    /* get the file descriptor */
    if ((audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        SDL_SetError("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", snd_strerror(rval));
        return (-1);
    }

    /* Trigger audio playback */
    rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
    if (rval < 0)
    {
        SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval));
        return (-1);
    }

    this->enabled = 1;

    /* Get the parent process id (we're the parent of the audio thread) */
    parent = getpid();

    /* We're really ready to rock and roll. :-) */
    return (0);
}
Пример #7
0
static int NTO_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	int rval;
	int format;
	Uint16 test_format;
	int twidth;
	int found;

#ifdef DEBUG_AUDIO
		fprintf(stderr, "NTO_OpenAudio\n");
#endif
	
	audio_handle = NULL;
	 this->enabled = 0;

	if ( pcm_buf != NULL ) {
		free((Uint8 *)pcm_buf); 
		pcm_buf = NULL;
	}
	 
	/* initialize channel transfer parameters to default */
	init_pcm_cparams(&cparams);

	/* Open the audio device */
	
	rval = snd_pcm_open_preferred(&audio_handle, &card_no, &device_no, OPEN_FLAGS);
	if ( rval < 0 ) {
		SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval));
		return(-1);
	}

    /* set to nonblocking mode */
    if ((rval = snd_pcm_nonblock_mode(audio_handle, 1))<0) //I assume 1 means on
    {
        SDL_SetError("snd_pcm_nonblock_mode failed: %s\n", snd_strerror(rval));
        return(-1);
    }

    /* enable count status parameter */
    if ((rval = snd_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP))<0)
    {
        SDL_SetError("snd_plugin_set_disable failed: %s\n", snd_strerror(rval));
        return(-1);
    }


	/* Try for a closest match on audio format */
	format = 0;
 	found = 0; // can't use format as SND_PCM_SFMT_U8 = 0 in nto
	for ( test_format = SDL_FirstAudioFormat(spec->format);	!found ; ) 

	{
#ifdef DEBUG_AUDIO
		fprintf(stderr, "Trying format 0x%4.4x spec->samples %d\n", test_format,spec->samples);
#endif
			/* if match found set format to equivalent ALSA format */
        switch ( test_format ) {
			case AUDIO_U8:
				format = SND_PCM_SFMT_U8;
				cparams.buf.block.frag_size = spec->samples * spec->channels;
				found = 1;
				break;
			case AUDIO_S8:
				format = SND_PCM_SFMT_S8;
				cparams.buf.block.frag_size = spec->samples * spec->channels;
				found = 1;
				break;
			case AUDIO_S16LSB:
				format = SND_PCM_SFMT_S16_LE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_S16MSB:
				format = SND_PCM_SFMT_S16_BE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_U16LSB:
				format = SND_PCM_SFMT_U16_LE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_U16MSB:
				format = SND_PCM_SFMT_U16_BE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			default:
				break;
		}
		if ( ! found ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	
	/* assumes test_format not 0 on success */
	if ( test_format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	
	spec->format = test_format;

	/* Set the audio format */
	cparams.format.format = format;

	/* Set mono or stereo audio (currently only two channels supported) */
	cparams.format.voices = spec->channels;
	
#ifdef DEBUG_AUDIO
	fprintf(stderr,"intializing channels %d\n", cparams.format.voices);
#endif

	
	/* Set rate */
	cparams.format.rate = spec->freq ;

	/* Setup the transfer parameters according to cparams */
	rval = snd_pcm_plugin_params(audio_handle, &cparams);
	if (rval < 0) {
		SDL_SetError("snd_pcm_channel_params failed: %s\n", snd_strerror (rval));
		return(-1);
	}

    /*  Make sure channel is setup right one last time */
    memset( &csetup, 0, sizeof( csetup ) );
    csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ( snd_pcm_plugin_setup( audio_handle, &csetup ) < 0 )
    {
        SDL_SetError("Unable to setup playback channel\n" );
        return(-1);
    }
    else
    {
#ifdef DEBUG_AUDIO
        fprintf(stderr,"requested format: %d\n",cparams.format.format);
        fprintf(stderr,"requested frag size: %d\n",cparams.buf.block.frag_size);
        fprintf(stderr,"requested max frags: %d\n\n",cparams.buf.block.frags_max);

        fprintf(stderr,"real format: %d\n", csetup.format.format );
        fprintf(stderr,"real frag size : %d\n", csetup.buf.block.frag_size );
		fprintf(stderr,"real max frags : %d\n", csetup.buf.block.frags_max );
#endif // DEBUG_AUDIO
    }


    /*  Allocate memory to the audio buffer and initialize with silence
        (Note that buffer size must be a multiple of fragment size, so find closest multiple)
    */
    
    twidth = snd_pcm_format_width(format);
    if (twidth < 0) {
        printf("snd_pcm_format_width failed\n");
        twidth = 0;
    }
    
#ifdef DEBUG_AUDIO
    fprintf(stderr,"format is %d bits wide\n",twidth);
#endif      
    
    pcm_len = spec->size ;
    
  
#ifdef DEBUG_AUDIO    
    fprintf(stderr,"pcm_len set to %d\n", pcm_len);
#endif
    
    if (pcm_len == 0)
    {
        pcm_len = csetup.buf.block.frag_size;
    }
    
    pcm_buf = (Uint8*)malloc(pcm_len);
    if (pcm_buf == NULL) {
        SDL_SetError("pcm_buf malloc failed\n");
        return(-1);
    }
    memset(pcm_buf,spec->silence,pcm_len);

#ifdef DEBUG_AUDIO
	fprintf(stderr,"pcm_buf malloced and silenced.\n");
#endif

    /* get the file descriptor */
    if( (audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
       fprintf(stderr, "snd_pcm_file_descriptor failed with error code: %d\n", audio_fd);
    }

	/* Trigger audio playback */
	rval = snd_pcm_plugin_prepare( audio_handle, SND_PCM_CHANNEL_PLAYBACK);
	if (rval < 0) {
       SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rval));
       return(-1);
	}
	
	 this->enabled = 1;
	 
	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #8
0
cst_audiodev *audio_open_alsa(int sps, int channels, cst_audiofmt fmt)
{
    snd_pcm_channel_info_t pinfo;
    snd_pcm_channel_params_t params;
    snd_pcm_channel_setup_t setup;
    snd_pcm_t *pcm;
    cst_audiodev *ad;
    int err;

#ifdef __QNXNTO__
    if (snd_pcm_open_preferred(&pcm,&alsa_card,&alsa_device,SND_PCM_OPEN_PLAYBACK) < 0)
    {
	cst_errmsg("alsa_audio: failed to open audio device\n");
	cst_error();
    }
    if (snd_pcm_plugin_set_disable(pcm,PLUGIN_DISABLE_MMAP) < 0)
    {
	cst_errmsg("alsa_audio: failed to disable mmap\n");
	snd_pcm_close(pcm);
	cst_error();
    }
#else
    if (snd_pcm_open(&pcm,alsa_card,alsa_device,SND_PCM_OPEN_PLAYBACK) < 0)
    {
	cst_errmsg("alsa_audio: failed to open audio device\n");
	cst_error();
    }
#endif


    memset(&pinfo, 0, sizeof(pinfo));
    memset(&params, 0, sizeof(params));
    memset(&setup, 0, sizeof(setup));

    pinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
    snd_pcm_plugin_info(pcm,&pinfo);

    params.mode = SND_PCM_MODE_BLOCK;
    params.channel = SND_PCM_CHANNEL_PLAYBACK;
    params.start_mode = SND_PCM_START_DATA;
    params.stop_mode = SND_PCM_STOP_STOP;

    params.buf.block.frag_size = pinfo.max_fragment_size;
    params.buf.block.frags_max = 1;
    params.buf.block.frags_min = 1;
    
    params.format.interleave = 1;
    params.format.rate = sps;
    params.format.voices = channels;

    switch (fmt)
    {
    case CST_AUDIO_LINEAR16:
	if (CST_LITTLE_ENDIAN)
	    params.format.format = SND_PCM_SFMT_S16_LE;
	else
	    params.format.format = SND_PCM_SFMT_S16_BE;
	break;
    case CST_AUDIO_LINEAR8:
	params.format.format = SND_PCM_SFMT_U8;
	break;
    case CST_AUDIO_MULAW:
	params.format.format = SND_PCM_SFMT_MU_LAW;
	break;
    }

    if((err = snd_pcm_plugin_params(pcm,&params)) < 0)
    {
	cst_errmsg("alsa_audio params setting failed: %s\n",snd_strerror(err));
	snd_pcm_close(pcm);	
	cst_error();
    }
    if((err = snd_pcm_plugin_setup(pcm,SND_PCM_CHANNEL_PLAYBACK)) > 0) {
	cst_errmsg("alsa_audio sound prepare setting failed: %s\n",snd_strerror(err));
	snd_pcm_close(pcm);
	cst_error();
    }
    if((err = snd_pcm_plugin_prepare(pcm,SND_PCM_CHANNEL_PLAYBACK)) > 0) {
	cst_errmsg("alsa_audio sound prepare setting failed: %s\n",snd_strerror(err));
	snd_pcm_close(pcm);
	cst_error();
    }

    pinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
    snd_pcm_plugin_info(pcm,&pinfo);

    ad = cst_alloc(cst_audiodev, 1);
    ad->platform_data = pcm;
    ad->sps = ad->real_sps = sps;
    ad->channels = ad->real_channels = channels;
    ad->fmt = ad->real_fmt = fmt;

    return ad;
}
Пример #9
0
static pj_status_t bb10_open_capture (struct bb10_stream *stream,
                                      const pjmedia_aud_param *param)
{
    int ret = 0;
    unsigned int rate;
    unsigned long tmp_buf_size;
    int card = -1;
    int dev = 0;
    int frame_size;
    snd_pcm_channel_info_t pi;
    snd_mixer_group_t group;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;
    unsigned int handle;

    if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt)
        return PJMEDIA_EAUD_INVDEV;

#if PJ_BBSDK_VER >= 0x100006
    if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VOICE,
                                               &stream->ca_pcm,
                                               &handle,
                                               "/dev/snd/voicec",
                                               SND_PCM_OPEN_CAPTURE)) < 0)
    {
	TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret));
	return PJMEDIA_EAUD_SYSERR;
    }
#else
    /* BB10 Audio init here (not prepare) */
    PJ_UNUSED_ARG(handle);
    if ((ret = snd_pcm_open_preferred (&stream->ca_pcm, &card, &dev,
                                       SND_PCM_OPEN_CAPTURE)) < 0)
    {
        TRACE_((THIS_FILE, "snd_pcm_open_preferred ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }
#endif

    /* sample reads the capabilities of the capture */
    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_CAPTURE;
    if ((ret = snd_pcm_plugin_info (stream->ca_pcm, &pi)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    /* Request the VoIP parameters
     * These parameters are different to waverec sample
     */
    memset (&pp, 0, sizeof (pp));
    /* Blocking read */
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_CAPTURE;
    pp.start_mode = SND_PCM_START_DATA;
    /* Auto-recover from errors */
    pp.stop_mode = SND_PCM_STOP_ROLLOVER;
    /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */
    pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2;
    /* Not applicable for capture hence -1 */
    pp.buf.block.frags_max = -1;
    pp.buf.block.frags_min = 1;
    pp.format.interleave = 1;
    /* HARD CODE for the time being PJMEDIA expects 16khz */
    PJ_TODO(REMOVE_SAMPLE_RATE_HARD_CODE);
    pj_assert(param->clock_rate == VOIP_SAMPLE_RATE * 2);
    pp.format.rate = VOIP_SAMPLE_RATE*2;
    pp.format.voices = 1;
    pp.format.format = SND_PCM_SFMT_S16_LE;

    /* make the request */
    if ((ret = snd_pcm_plugin_params (stream->ca_pcm, &pp)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    /* Again based on the sample */
    memset (&setup, 0, sizeof (setup));
    memset (&group, 0, sizeof (group));
    setup.channel = SND_PCM_CHANNEL_CAPTURE;
    setup.mixer_gid = &group.gid;
    if ((ret = snd_pcm_plugin_setup (stream->ca_pcm, &setup)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    frame_size = setup.buf.block.frag_size;

    if (group.gid.name[0] == 0) {
    } else {
    }

    /* frag_size should be 160 */
    frame_size = setup.buf.block.frag_size;

    /* END BB10 init */

    /* Set clock rate */
    rate = param->clock_rate;
    stream->ca_frames = (unsigned long) param->samples_per_frame /
			param->channel_count;

    /* Set the sound device buffer size and latency */
    if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) {
        tmp_buf_size = (rate / 1000) * param->input_latency_ms;
    } else {
        tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_REC_LATENCY;
    }

    stream->param.input_latency_ms = tmp_buf_size / (rate / 1000);

    /* Set our buffer */
    stream->ca_buf_size = stream->ca_frames * param->channel_count *
			  (param->bits_per_sample/8);
    stream->ca_buf = (char *)pj_pool_alloc (stream->pool, stream->ca_buf_size);

    TRACE_((THIS_FILE, "bb10_open_capture: ca_frames = %d clock = %d",
                       stream->ca_frames, param->clock_rate));

    return PJ_SUCCESS;
}
Пример #10
0
static pj_status_t bb10_open_playback (struct bb10_stream *stream,
                                       const pjmedia_aud_param *param)
{
    int card = -1;
    int dev = 0;
    int ret = 0;
    snd_pcm_channel_info_t pi;
    snd_pcm_channel_setup_t setup;
    snd_mixer_group_t group;
    snd_pcm_channel_params_t pp;
    unsigned int rate;
    unsigned long tmp_buf_size;
    unsigned int handle;

    if (param->play_id < 0 || param->play_id >= stream->af->dev_cnt) {
        return PJMEDIA_EAUD_INVDEV;
    }

#if PJ_BBSDK_VER >= 0x100006
    if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VOICE,
                                               &stream->pb_pcm, &handle,
                                               "/dev/snd/voicep",
                                               SND_PCM_OPEN_PLAYBACK)) < 0)
    {
        TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

#else
    if ((ret = snd_pcm_open_preferred (&stream->pb_pcm, &card, &dev,
                                       SND_PCM_OPEN_PLAYBACK)) < 0)
    {
        TRACE_((THIS_FILE, "snd_pcm_open_preferred ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }
#endif

    /* TODO PJ_ZERO */
    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((ret = snd_pcm_plugin_info (stream->pb_pcm, &pi)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    memset (&pp, 0, sizeof (pp));

    /* Request VoIP compatible capabilities
     * On simulator frag_size is always negotiated to 170
     */
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_DATA;
    pp.stop_mode = SND_PCM_STOP_ROLLOVER;
    /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */
    pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2;
    /* Increasing this internal buffer count delays write failure in the loop */
    pp.buf.block.frags_max = 4;
    pp.buf.block.frags_min = 1;
    pp.format.interleave = 1;
    /* HARD CODE for the time being PJMEDIA expects 16khz */
    PJ_TODO(REMOVE_SAMPLE_RATE_HARD_CODE);
    pj_assert(param->clock_rate == VOIP_SAMPLE_RATE * 2);
    pp.format.rate = VOIP_SAMPLE_RATE*2;
    pp.format.voices = 1;
    pp.format.format = SND_PCM_SFMT_S16_LE;

    /* Make the calls as per the wave sample */
    if ((ret = snd_pcm_plugin_params (stream->pb_pcm, &pp)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    memset (&setup, 0, sizeof (setup));
    memset (&group, 0, sizeof (group));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    setup.mixer_gid = &group.gid;

    if ((ret = snd_pcm_plugin_setup (stream->pb_pcm, &setup)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    if (group.gid.name[0] == 0) {
        return PJMEDIA_EAUD_SYSERR;
    }

    rate = param->clock_rate;
    /* Set the sound device buffer size and latency */
    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) {
        tmp_buf_size = (rate / 1000) * param->output_latency_ms;
    } else {
	tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
    }
    /* Set period size to samples_per_frame frames. */
    stream->pb_frames = param->samples_per_frame;
    stream->param.output_latency_ms = tmp_buf_size / (rate / 1000);

    /* Set our buffer */
    stream->pb_buf_size = stream->pb_frames * param->channel_count *
                          (param->bits_per_sample/8);
    stream->pb_buf = (char *) pj_pool_alloc(stream->pool, stream->pb_buf_size);

    TRACE_((THIS_FILE, "bb10_open_playback: pb_frames = %d clock = %d",
                       stream->pb_frames, param->clock_rate));

    return PJ_SUCCESS;
}
Пример #11
0
Error AudioDriverBB10::init(const char *p_name) {

	active = false;
	thread_exited = false;
	exit_thread = false;
	pcm_open = false;
	samples_in = NULL;
	samples_out = NULL;

	mix_rate = 44100;
	speaker_mode = SPEAKER_MODE_STEREO;

	char *dev_name;
	if (p_name == NULL) {
		dev_name = "pcmPreferred";
	} else {
		dev_name = (char *)p_name;
	}
	printf("******** reconnecting to device %s\n", dev_name);
	int ret = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK);
	ERR_FAIL_COND_V(ret < 0, FAILED);
	pcm_open = true;

	snd_pcm_channel_info_t cinfo;
	zeromem(&cinfo, sizeof(cinfo));
	cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
	snd_pcm_plugin_info(pcm_handle, &cinfo);

	printf("rates %i, %i, %i, %i, %i\n", cinfo.rates, cinfo.rates & SND_PCM_RATE_44100, cinfo.rates & SND_PCM_RATE_32000, cinfo.rates & SND_PCM_RATE_22050, cinfo.max_rate);

	mix_rate = cinfo.max_rate;

	printf("formats %i, %i, %i\n", cinfo.formats, cinfo.formats & SND_PCM_FMT_S16_BE, cinfo.formats & SND_PCM_FMT_S16_LE);
	ERR_FAIL_COND_V(!(cinfo.formats & SND_PCM_FMT_S16_LE), FAILED);

	printf("voices %i\n", cinfo.max_voices);
	speaker_mode = SPEAKER_MODE_STEREO;

	snd_pcm_channel_params_t cp;
	zeromem(&cp, sizeof(cp));
	cp.mode = SND_PCM_MODE_BLOCK;
	cp.channel = SND_PCM_CHANNEL_PLAYBACK;
	cp.start_mode = SND_PCM_START_DATA;
	cp.stop_mode = SND_PCM_STOP_STOP;
	//cp.buf.block.frag_size = cinfo.max_fragment_size;
	cp.buf.block.frag_size = 512;
	cp.buf.block.frags_max = 1;
	cp.buf.block.frags_min = 1;
	cp.format.interleave = 1;
	cp.format.rate = mix_rate;
	cp.format.voices = speaker_mode;
	cp.format.format = SND_PCM_SFMT_S16_LE;

	ret = snd_pcm_plugin_params(pcm_handle, &cp);
	printf("ret is %i, %i\n", ret, cp.why_failed);
	ERR_FAIL_COND_V(ret < 0, FAILED);

	ret = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
	ERR_FAIL_COND_V(ret < 0, FAILED);

	snd_mixer_group_t group;
	zeromem(&group, sizeof(group));
	snd_pcm_channel_setup_t setup;
	zeromem(&setup, sizeof(setup));
	setup.channel = SND_PCM_CHANNEL_PLAYBACK;
	setup.mode = SND_PCM_MODE_BLOCK;
	setup.mixer_gid = &group.gid;
	ret = snd_pcm_plugin_setup(pcm_handle, &setup);
	ERR_FAIL_COND_V(ret < 0, FAILED);

	pcm_frag_size = setup.buf.block.frag_size;
	pcm_max_frags = 1;

	sample_buf_count = pcm_frag_size * pcm_max_frags / 2;
	printf("sample count %i, %i, %i\n", sample_buf_count, pcm_frag_size, pcm_max_frags);
	samples_in = memnew_arr(int32_t, sample_buf_count);
	samples_out = memnew_arr(int16_t, sample_buf_count);

	thread = Thread::create(AudioDriverBB10::thread_func, this);

	return OK;
};
Пример #12
0
/*
 * General setup of the libasound audio mixer and pcm components.
 * Some of the settings are based on the format of the wav data.
 */
int
setup_snd(const char * name)
{
    int fragsize = -1;
    int num_frags = -1;
    int rtn;
    char *dev_name;

    if (NULL == name) {
        dev_name = "pcmPreferred";
    } else {
        dev_name = (char *) name;
    }

    if ((rtn = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_open_name failed: %s\n", snd_strerror(rtn));
        show_dialog_message(msg);
        return FAILURE;
    }

    if ((rtn = snd_pcm_info(pcm_handle, &info)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_info failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }
    card = info.card;

    /* disabling mmap is not actually required in this example but it is included to
     * demonstrate how it is used when it is required.
     */
    if ((rtn = snd_pcm_plugin_set_disable(pcm_handle, PLUGIN_DISABLE_MMAP)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }

    memset(&pi, 0, sizeof(pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_info(pcm_handle, &pi)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_plugin_info failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }

    memset(&pp, 0, sizeof(pp));

    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_STOP;
    pp.buf.block.frag_size = pi.max_fragment_size;

    if (fragsize != -1) {
        pp.buf.block.frag_size = fragsize;
    }

    pp.buf.block.frags_max = num_frags;
    pp.buf.block.frags_min = 1;

    pp.format.interleave = 1;
    pp.format.rate = sample_rate;
    pp.format.voices = sample_channels;

    if (ENDIAN_LE16(wav_header.format_tag) == 6)
        pp.format.format = SND_PCM_SFMT_A_LAW;
    else if (ENDIAN_LE16(wav_header.format_tag) == 7)
        pp.format.format = SND_PCM_SFMT_MU_LAW;
    else if (sample_bits == 8)
        pp.format.format = SND_PCM_SFMT_U8;
    else if (sample_bits == 24)
        pp.format.format = SND_PCM_SFMT_S24;
    else
        pp.format.format = SND_PCM_SFMT_S16_LE;

    strcpy(pp.sw_mixer_subchn_name, "Wave playback channel");
    if ((rtn = snd_pcm_plugin_params(pcm_handle, &pp)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_plugin_params failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }

    if ((rtn = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }

    memset(&setup, 0, sizeof(setup));
    memset(&group, 0, sizeof(group));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    setup.mixer_gid = &group.gid;

    if ((rtn = snd_pcm_plugin_setup(pcm_handle, &setup)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_pcm_plugin_setup failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }

    if (group.gid.name[0] == 0) {
        snprintf(msg, MSG_SIZE, "Mixer Pcm Group [%s] Not Set \n", group.gid.name);
        goto setup_failure;
    }

    if ((rtn = snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) {
        snprintf(msg, MSG_SIZE, "snd_mixer_open failed: %s\n", snd_strerror(rtn));
        goto setup_failure;
    }

    char tmp[MSG_SIZE];
    snprintf(msg, MSG_SIZE, "Format %s \n", snd_pcm_get_format_name(setup.format.format));
    snprintf(tmp, MSG_SIZE, "Frag Size %d \n", setup.buf.block.frag_size);
    strlcat(msg, tmp, MSG_SIZE);
    snprintf(tmp, MSG_SIZE, "Total Frags %d \n", setup.buf.block.frags);
    strlcat(msg, tmp, MSG_SIZE);
    snprintf(tmp, MSG_SIZE, "Rate %d \n", setup.format.rate);
    strlcat(msg, tmp, MSG_SIZE);
    snprintf(tmp, MSG_SIZE, "Voices %d \n", setup.format.voices);
    strlcat(msg, tmp, MSG_SIZE);
    snprintf(tmp, MSG_SIZE, "Mixer Pcm Group [%s]\n", group.gid.name);
    strlcat(msg, tmp, MSG_SIZE);
    show_dialog_message(msg);

    return SUCCESS;

setup_failure:
    show_dialog_message(msg);
    snd_pcm_close(pcm_handle);
    return FAILURE;
}
Пример #13
0
/* public methods (static but exported through the sysdep_dsp or plugin
   struct) */
static void *alsa_dsp_create(const void *flags)
{
	int i, j;
//	audio_buf_info info;
	struct alsa_dsp_priv_data *priv = NULL;
	struct sysdep_dsp_struct *dsp = NULL;
	const struct sysdep_dsp_create_params *params = flags;
	const char *device = params->device;
	int err;
	int bytespersample;

	fprintf(stderr,"info: dsp_create called\n");
   
	/* allocate the dsp struct */
	if (!(dsp = calloc(1, sizeof(struct sysdep_dsp_struct))))
	{
		fprintf(stderr,
			"error: malloc failed for struct sysdep_dsp_struct\n");
		return NULL;
	}
   
	/* alloc private data */
	if(!(priv = calloc(1, sizeof(struct alsa_dsp_priv_data))))
	{
		fprintf(stderr,
			"error: malloc failed for struct dsp_priv_data\n");
		alsa_dsp_destroy(dsp);
		return NULL;
	}
   
	/* fill in the functions and some data */
	dsp->_priv = priv;
	dsp->get_freespace = alsa_dsp_get_freespace;
	dsp->write = alsa_dsp_write;
	dsp->destroy = alsa_dsp_destroy;
	dsp->hw_info.type = params->type;
	dsp->hw_info.samplerate = params->samplerate;

	priv->audio_dev.bMute = 0;
	priv->audio_dev.m_AudioHandle = NULL;
	priv->audio_dev.m_MixerHandle = NULL;
	priv->audio_dev.m_Acard = 0;
	priv->audio_dev.m_Adevice = 0;


	if (preferred_device)
	{	
 		if((err = snd_pcm_open_preferred(&(priv->audio_dev.m_AudioHandle), &priv->audio_dev.m_Acard,
                                       &priv->audio_dev.m_Adevice, SND_PCM_OPEN_PLAYBACK)) < 0)
    	{
			fprintf(stderr,"info: snd_pcm_open_preferred failed: %s \n", snd_strerror(err));
    	            alsa_dsp_destroy(dsp);
			return NULL;
    	}
	}
	else
	{
		fprintf(stderr,"info: audio is using primary device\n");
		if((err = snd_pcm_open(&(priv->audio_dev.m_AudioHandle), 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0)
		{
			fprintf(stderr,"info: snd_pcm_open failed: %s \n", snd_strerror(err));
			alsa_dsp_destroy(dsp);
			return NULL;
		}
	}
	
	memset (&(priv->audio_dev.m_Achaninfo), 0, sizeof (priv->audio_dev.m_Achaninfo));
	priv->audio_dev.m_Achaninfo.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_plugin_info (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Achaninfo))) < 0)
	{
		fprintf (stderr, "info: snd_pcm_plugin_info failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}

	//needed to enable the count status parameter, mmap plugin disables this
	if((err = snd_plugin_set_disable(priv->audio_dev.m_AudioHandle, PLUGIN_DISABLE_MMAP)) < 0)
	{
		fprintf (stderr, "info: snd_plugin_set_disable failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}

	/* calculate and set the fragsize & number of frags */
	/* fragsize (as power of 2) */
	i = 8;
	if (dsp->hw_info.type & SYSDEP_DSP_16BIT) i++;
	if (dsp->hw_info.type & SYSDEP_DSP_STEREO) i++;
	i += dsp->hw_info.samplerate / 22000;

	/* number of frags */
	j = ((dsp->hw_info.samplerate * alsa_dsp_bytes_per_sample[dsp->hw_info.type] *
		params->bufsize) / (0x01 << i)) + 1;

	bytespersample=1;
//	dsp->hw_info.type &= ~SYSDEP_DSP_16BIT;
//	dsp->hw_info.type &= ~SYSDEP_DSP_STEREO;
	if (dsp->hw_info.type & SYSDEP_DSP_16BIT) bytespersample++;
	if (dsp->hw_info.type & SYSDEP_DSP_STEREO) bytespersample <<= 1;
	
	memset( &(priv->audio_dev.m_Aparams), 0, sizeof(priv->audio_dev.m_Aparams));
	priv->audio_dev.m_Aparams.mode = SND_PCM_MODE_BLOCK;
	priv->audio_dev.m_Aparams.channel = SND_PCM_CHANNEL_PLAYBACK;
	priv->audio_dev.m_Aparams.start_mode = SND_PCM_START_FULL;
	priv->audio_dev.m_Aparams.stop_mode = SND_PCM_STOP_ROLLOVER;
#if 0
	priv->audio_dev.m_Aparams.buf.stream.queue_size = 512 * bytespersample;
	priv->audio_dev.m_Aparams.buf.stream.fill = SND_PCM_FILL_SILENCE;
	priv->audio_dev.m_Aparams.buf.stream.max_fill = 512 * bytespersample;
#endif
        priv->audio_dev.m_Aparams.format.interleave = 1;
        priv->audio_dev.m_Aparams.format.rate = dsp->hw_info.samplerate;
        priv->audio_dev.m_Aparams.format.voices = (dsp->hw_info.type & SYSDEP_DSP_STEREO) ? 2 : 1;

	priv->audio_dev.m_Aparams.buf.block.frag_size = 1000;
	priv->audio_dev.m_Aparams.buf.block.frags_min = 1;
	priv->audio_dev.m_Aparams.buf.block.frags_max = 5;

        priv->audio_dev.m_BytesPerSample = bytespersample;
        priv->audio_dev.m_Aparams.format.format = 
#ifdef LSB_FIRST
				(dsp->hw_info.type & SYSDEP_DSP_16BIT) ? SND_PCM_SFMT_S16_LE : SND_PCM_SFMT_U8; 
#else
				(dsp->hw_info.type & SYSDEP_DSP_16BIT) ? SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_U8;
#endif

	if ((err = snd_pcm_plugin_params (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Aparams))) < 0)
	{
		fprintf (stderr, "info: snd_pcm_plugin_params failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}

	if ((err = snd_pcm_plugin_prepare (priv->audio_dev.m_AudioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
	{
		fprintf (stderr, "warning: snd_pcm_plugin_prepare failed: %s\n", snd_strerror (err));
	}

	memset (&(priv->audio_dev.m_Asetup), 0, sizeof (priv->audio_dev.m_Asetup));
	priv->audio_dev.m_Asetup.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_plugin_setup (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Asetup))) < 0)
	{
		fprintf (stderr, "warning: snd_pcm_plugin_setup failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}
	
	memset (&(priv->audio_dev.m_Astatus), 0, sizeof (priv->audio_dev.m_Astatus));
	priv->audio_dev.m_Astatus.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_plugin_status (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Astatus))) < 0)
	{
		fprintf (stderr, "warning: snd_pcm_plugin_status failed: %s\n", snd_strerror (err));
        }
	dsp->hw_info.bufsize = priv->audio_dev.m_Asetup.buf.stream.queue_size  
	             		/ alsa_dsp_bytes_per_sample[dsp->hw_info.type];
#if 0
	if ((err=snd_pcm_nonblock_mode(priv->audio_dev.m_AudioHandle, 1))<0)
	{
		fprintf(stderr, "error: error with non block mode: %s\n", snd_strerror (err));
	}
#endif
	return dsp;
}
Пример #14
0
bool QnxAudioInput::open()
{
    if (!m_format.isValid() || m_format.sampleRate() <= 0) {
        if (!m_format.isValid())
            qWarning("QnxAudioInput: open error, invalid format.");
        else
            qWarning("QnxAudioInput: open error, invalid sample rate (%d).", m_format.sampleRate());

        return false;
    }

    int errorCode = 0;

    int card = 0;
    int device = 0;
    if ((errorCode = snd_pcm_open_preferred(&m_pcmHandle, &card, &device, SND_PCM_OPEN_CAPTURE)) < 0) {
        qWarning("QnxAudioInput: open error, couldn't open card (0x%x)", -errorCode);
        return false;
    }

    // Necessary so that bytesFree() which uses the "free" member of the status struct works
    snd_pcm_plugin_set_disable(m_pcmHandle, PLUGIN_DISABLE_MMAP);

    snd_pcm_channel_info_t info;
    memset(&info, 0, sizeof(info));
    info.channel = SND_PCM_CHANNEL_CAPTURE;
    if ((errorCode = snd_pcm_plugin_info(m_pcmHandle, &info)) < 0) {
        qWarning("QnxAudioInput: open error, couldn't get channel info (0x%x)", -errorCode);
        close();
        return false;
    }

    snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(m_format, QAudio::AudioInput, info.max_fragment_size);

    if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, &params)) < 0) {
        qWarning("QnxAudioInput: open error, couldn't set channel params (0x%x)", -errorCode);
        close();
        return false;
    }

    if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE)) < 0) {
        qWarning("QnxAudioInput: open error, couldn't prepare channel (0x%x)", -errorCode);
        close();
        return false;
    }

    snd_pcm_channel_setup_t setup;

    memset(&setup, 0, sizeof(setup));
    setup.channel = SND_PCM_CHANNEL_CAPTURE;
    if ((errorCode = snd_pcm_plugin_setup(m_pcmHandle, &setup)) < 0) {
        qWarning("QnxAudioInput: open error, couldn't get channel setup (0x%x)", -errorCode);
        close();
        return false;
    }

    m_periodSize = qMin(2048, setup.buf.block.frag_size);

    m_clockStamp.restart();
    m_timeStamp.restart();
    m_elapsedTimeOffset = 0;
    m_totalTimeValue = 0;
    m_bytesRead = 0;

    m_pcmNotifier = new QSocketNotifier(snd_pcm_file_descriptor(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE),
                                        QSocketNotifier::Read, this);
    connect(m_pcmNotifier, SIGNAL(activated(int)), SLOT(userFeed()));

    return true;
}
Пример #15
0
static pj_status_t bb10_open_playback (struct bb10_stream *stream,
                                       const pjmedia_aud_param *param)
{
    int ret = 0;
    snd_pcm_channel_info_t pi;
    snd_pcm_channel_setup_t setup;
    snd_mixer_group_t group;
    snd_pcm_channel_params_t pp;
    unsigned int rate;
    unsigned long tmp_buf_size;

    if (param->play_id < 0 || param->play_id >= stream->af->dev_cnt) {
        return PJMEDIA_EAUD_INVDEV;
    }

    PJ_ASSERT_RETURN(param->bits_per_sample == 16, PJMEDIA_EAUD_SAMPFORMAT);

    /* Use the bb10 audio manager API to open as opposed to QNX core audio
     * Echo cancellation built in
     */
    if ((ret = audio_manager_snd_pcm_open_name(
	    AUDIO_TYPE_VIDEO_CHAT,
            &stream->pb_pcm, &stream->pb_audio_manager_handle,
            (char*)"voice",
            SND_PCM_OPEN_PLAYBACK)) < 0)
    {
        TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    /* Required call from January 2013 gold OS release */
    snd_pcm_plugin_set_disable(stream->pb_pcm, PLUGIN_DISABLE_MMAP);

    /* Required call from January 2013 gold OS release */
    snd_pcm_plugin_set_enable(stream->pb_pcm, PLUGIN_ROUTING);

    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((ret = snd_pcm_plugin_info (stream->pb_pcm, &pi)) < 0) {
	TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret));
	return PJMEDIA_EAUD_SYSERR;
    }

    memset (&pp, 0, sizeof (pp));

    /* Request VoIP compatible capabilities */
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_ROLLOVER;
    pp.buf.block.frag_size = param->samples_per_frame * param->bits_per_sample / 8;
    /* RIM recommends maximum of 5 */
    pp.buf.block.frags_max = 5;
    pp.buf.block.frags_min = 1;
    pp.format.interleave = 1;
    pp.format.rate = param->clock_rate;
    pp.format.voices = param->channel_count;
    pp.format.format = get_alsa_pcm_fmt(param);

    /* Make the calls as per the wave sample */
    if ((ret = snd_pcm_plugin_params (stream->pb_pcm, &pp)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    memset (&setup, 0, sizeof (setup));
    memset (&group, 0, sizeof (group));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    setup.mixer_gid = &group.gid;

    if ((ret = snd_pcm_plugin_setup (stream->pb_pcm, &setup)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    if (group.gid.name[0] == 0) {
        return PJMEDIA_EAUD_SYSERR;
    }

    rate = param->clock_rate;
    /* Set the sound device buffer size and latency */
    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) {
        tmp_buf_size = rate * param->output_latency_ms / 1000;
    } else {
	tmp_buf_size = rate * PJMEDIA_SND_DEFAULT_PLAY_LATENCY / 1000;
    }
    /* Set period size to samples_per_frame frames. */
    stream->pb_frames = param->samples_per_frame / param->channel_count;
    stream->param.output_latency_ms = tmp_buf_size * 1000 / rate;

    /* Set our buffer */
    stream->pb_buf_size = stream->pb_frames * param->channel_count *
                          param->bits_per_sample / 8;
    stream->pb_buf = (char *) pj_pool_alloc(stream->pool, stream->pb_buf_size);

    TRACE_((THIS_FILE, "bb10_open_playback: pb_frames = %d clock = %d",
                       stream->pb_frames, param->clock_rate));

    return PJ_SUCCESS;
}
Пример #16
0
static pj_status_t bb10_open_capture (struct bb10_stream *stream,
                                      const pjmedia_aud_param *param)
{
    int ret = 0;
    unsigned int rate;
    unsigned long tmp_buf_size;
    int frame_size;
    snd_pcm_channel_info_t pi;
    snd_mixer_group_t group;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;

    if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt)
        return PJMEDIA_EAUD_INVDEV;

    PJ_ASSERT_RETURN(param->bits_per_sample == 16, PJMEDIA_EAUD_SAMPFORMAT);

    if ((ret=audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT,
                                             &stream->ca_pcm,
                                             &stream->ca_audio_manager_handle,
                                             (char*)"voice",
                                             SND_PCM_OPEN_CAPTURE)) < 0)
    {
	TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret));
	return PJMEDIA_EAUD_SYSERR;
    }
    /* Required call from January 2013 gold OS release */
    snd_pcm_plugin_set_disable (stream->ca_pcm, PLUGIN_DISABLE_MMAP);

    /* Required call from January 2013 gold OS release */
    snd_pcm_plugin_set_enable(stream->ca_pcm, PLUGIN_ROUTING);

    /* sample reads the capabilities of the capture */
    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_CAPTURE;
    if ((ret = snd_pcm_plugin_info (stream->ca_pcm, &pi)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    /* Request the VoIP parameters
     * These parameters are different to waverec sample
     */
    memset (&pp, 0, sizeof (pp));
    /* Blocking read */
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_CAPTURE;
    pp.start_mode = SND_PCM_START_FULL;
    /* Auto-recover from errors */
    pp.stop_mode = SND_PCM_STOP_ROLLOVER;
    pp.buf.block.frag_size = param->samples_per_frame * param->bits_per_sample / 8;
    /* From January 2013 gold OS release. RIM recommend these for capture */
    pp.buf.block.frags_max = 3;
    pp.buf.block.frags_min = 1;
    pp.format.interleave = 1;
    pp.format.rate = param->clock_rate;
    pp.format.voices = param->channel_count;
    pp.format.format = get_alsa_pcm_fmt(param);

    /* make the request */
    if ((ret = snd_pcm_plugin_params (stream->ca_pcm, &pp)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    /* Again based on the sample */
    memset (&setup, 0, sizeof (setup));
    memset (&group, 0, sizeof (group));
    setup.channel = SND_PCM_CHANNEL_CAPTURE;
    setup.mixer_gid = &group.gid;
    if ((ret = snd_pcm_plugin_setup (stream->ca_pcm, &setup)) < 0) {
        TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret));
        return PJMEDIA_EAUD_SYSERR;
    }

    frame_size = setup.buf.block.frag_size;

    if (group.gid.name[0] == 0) {
    } else {
    }

    frame_size = setup.buf.block.frag_size;
    PJ_UNUSED_ARG(frame_size); /* Warning about unused var */

    /* Set clock rate */
    rate = param->clock_rate;
    stream->ca_frames = (unsigned long) param->samples_per_frame /
			param->channel_count;

    /* Set the sound device buffer size and latency */
    if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) {
        tmp_buf_size = rate * param->input_latency_ms / 1000;
    } else {
        tmp_buf_size = rate * PJMEDIA_SND_DEFAULT_REC_LATENCY / 1000;
    }

    stream->param.input_latency_ms = tmp_buf_size * 1000 / rate;

    /* Set our buffer */
    stream->ca_buf_size = stream->ca_frames * param->channel_count *
			  param->bits_per_sample / 8;
    stream->ca_buf = (char *)pj_pool_alloc (stream->pool, stream->ca_buf_size);

    TRACE_((THIS_FILE, "bb10_open_capture: ca_frames = %d clock = %d",
                       stream->ca_frames, param->clock_rate));

    return PJ_SUCCESS;
}
Пример #17
0
void *Audio_ALSA::open (AudioConfig &cfg, const char *)
{
    AudioConfig tmpCfg;

    if (_audioHandle != NULL)
    {
        _errorString = "ERROR: Device already in use";
        return NULL;
     }

#ifdef HAVE_ALSA_ASOUNDLIB_H
    snd_pcm_uframes_t    buffer_frames;
    snd_pcm_hw_params_t *hw_params = 0;

    if (snd_pcm_open (&_audioHandle, "default", SND_PCM_STREAM_PLAYBACK, 0))
    {
        _errorString = "ERROR: Could not open audio device.";
        goto open_error;
    }

    // May later be replaced with driver defaults.
    tmpCfg = cfg;

    if (snd_pcm_hw_params_malloc (&hw_params))
    {
        _errorString = "ERROR: could not malloc hwparams.";
        goto open_error;
    }

    if (snd_pcm_hw_params_any (_audioHandle, hw_params))
    {
        _errorString = "ERROR: could not initialize hw params";
        goto open_error;
    }

    if (snd_pcm_hw_params_set_access (_audioHandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED))
    {
        _errorString = "ERROR: could not set access type";
        goto open_error;
    }

    snd_pcm_format_t alsamode;
    switch (tmpCfg.precision)
    {
    case 8:
        tmpCfg.encoding = AUDIO_UNSIGNED_PCM;
        alsamode = SND_PCM_FORMAT_U8;
        break;
    case 16:
        tmpCfg.encoding = AUDIO_SIGNED_PCM;
        alsamode = SND_PCM_FORMAT_S16;
        break;
    default:
        _errorString = "ERROR: set desired number of bits for audio device.";
        goto open_error;
    }

    if (snd_pcm_hw_params_set_format (_audioHandle, hw_params, alsamode))
    {
        _errorString = "ERROR: could not set sample format";
        goto open_error;
    }

    if (snd_pcm_hw_params_set_channels (_audioHandle, hw_params, tmpCfg.channels))
    {
        _errorString = "ERROR: could not set channel count";
        goto open_error;
    }

    {   // Gentoo bug #98769, comment 4
        unsigned int rate = tmpCfg.frequency;
        if (snd_pcm_hw_params_set_rate_near (_audioHandle, hw_params, &rate, 0))
        {
            _errorString = "ERROR: could not set sample rate";
            goto open_error;
        }
    }

    _alsa_to_frames_divisor = tmpCfg.channels * tmpCfg.precision / 8;
    buffer_frames = 4096;
    snd_pcm_hw_params_set_period_size_near(_audioHandle, hw_params, &buffer_frames, 0);

    if (snd_pcm_hw_params (_audioHandle, hw_params))
    {
        _errorString = "ERROR: could not set hw parameters";
        goto open_error;
    }

    snd_pcm_hw_params_free (hw_params);
    hw_params = 0;

    if (snd_pcm_prepare (_audioHandle))
    {
        _errorString = "ERROR: could not prepare audio interface for use";
        goto open_error;
    }

    tmpCfg.bufSize = buffer_frames * _alsa_to_frames_divisor;					
#else // HAVE_ALSA_ASOUNDLIB_H
    // Obsolete interface
    int mask, wantedFormat, format;
    int rtn;
    int card = -1, dev = 0;
   
    if ((rtn = snd_pcm_open_preferred (&_audioHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK)))
    {
        _errorString = "ERROR: Could not open audio device.";
        goto open_error;
    }
    
    // Transfer input parameters to this object.
    // May later be replaced with driver defaults.
    tmpCfg = cfg;

    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;
 
    snd_pcm_channel_info_t pi;
   
    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_info (_audioHandle, &pi)))
    {
        _errorString = "ALSA: snd_pcm_plugin_info failed.";
        goto open_error;
    }
			
    memset(&pp, 0, sizeof (pp));
	
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_STOP;
				     
    pp.buf.block.frag_size = pi.max_fragment_size;

    pp.buf.block.frags_max = 1;
    pp.buf.block.frags_min = 1;
   
    pp.format.interleave = 1;
    pp.format.rate = tmpCfg.frequency;
    pp.format.voices = tmpCfg.channels;
   
    // Set sample precision and type of encoding.
    if ( tmpCfg.precision == 8 )
    {
        tmpCfg.encoding = AUDIO_UNSIGNED_PCM;
        pp.format.format = SND_PCM_SFMT_U8;
    }
    if ( tmpCfg.precision == 16 )
    {
        tmpCfg.encoding = AUDIO_SIGNED_PCM;
        pp.format.format = SND_PCM_SFMT_S16_LE;
    }

    if ((rtn = snd_pcm_plugin_params (_audioHandle, &pp)) < 0)
    {
        _errorString = "ALSA: snd_pcm_plugin_params failed.";
        goto open_error;
    }
   
    if ((rtn = snd_pcm_plugin_prepare (_audioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        _errorString = "ALSA: snd_pcm_plugin_prepare failed.";
        goto open_error;
    }
   
    memset (&setup, 0, sizeof (setup));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_setup (_audioHandle, &setup)) < 0)
    {
        _errorString = "ALSA: snd_pcm_plugin_setup failed.";
        goto open_error;
    }

    tmpCfg.bufSize = setup.buf.block.frag_size;
#endif
    
#ifdef HAVE_EXCEPTIONS
    _sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize];
#else
    _sampleBuffer = new int_least8_t[tmpCfg.bufSize];
#endif

    if (!_sampleBuffer)
    {
        _errorString = "AUDIO: Unable to allocate memory for sample buffers.";
        goto open_error;
    }

    // Setup internal Config
    _settings = tmpCfg;
    // Update the users settings
    getConfig (cfg);
    return _sampleBuffer;

open_error:
#ifdef HAVE_ALSA_ASOUNDLIB_H
    if (hw_params)
        snd_pcm_hw_params_free (hw_params);
#endif
    if (_audioHandle != NULL)
        close ();
    perror ("ALSA");
    return NULL;
}
Пример #18
0
void *Audio_ALSA::open (AudioConfig &cfg, const char *)
{
    AudioConfig tmpCfg;
    int mask, wantedFormat, format;
    int rtn;
    int card = -1, dev = 0;
   
    if (_audioHandle != NULL)
    {
        _errorString = "ERROR: Device already in use";
        return NULL;
    }

    if ((rtn = snd_pcm_open_preferred (&_audioHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK)))
    {
        _errorString = "ERROR: Could not open audio device.";
        goto open_error;
    }
    
    // Transfer input parameters to this object.
    // May later be replaced with driver defaults.
    tmpCfg = cfg;

    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;
 
    snd_pcm_channel_info_t pi;
   
    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_info (_audioHandle, &pi)))
    {
        _errorString = "ALSA: snd_pcm_plugin_info failed.";
        goto open_error;
    }
			
    memset(&pp, 0, sizeof (pp));
	
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_STOP;
				     
    pp.buf.block.frag_size = pi.max_fragment_size;

    pp.buf.block.frags_max = 1;
    pp.buf.block.frags_min = 1;
   
    pp.format.interleave = 1;
    pp.format.rate = tmpCfg.frequency;
    pp.format.voices = tmpCfg.channels;
   
    // Set sample precision and type of encoding.
    if ( tmpCfg.precision == 8 )
    {
        tmpCfg.encoding = AUDIO_UNSIGNED_PCM;
        pp.format.format = SND_PCM_SFMT_U8;
    }
    if ( tmpCfg.precision == 16 )
    {
        tmpCfg.encoding = AUDIO_SIGNED_PCM;
        pp.format.format = SND_PCM_SFMT_S16_LE;
    }

    if ((rtn = snd_pcm_plugin_params (_audioHandle, &pp)) < 0)
    {
        _errorString = "ALSA: snd_pcm_plugin_params failed.";
        goto open_error;
    }
   
    if ((rtn = snd_pcm_plugin_prepare (_audioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        _errorString = "ALSA: snd_pcm_plugin_prepare failed.";
        goto open_error;
    }
   
    memset (&setup, 0, sizeof (setup));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_setup (_audioHandle, &setup)) < 0)
    {
        _errorString = "ALSA: snd_pcm_plugin_setup failed.";
        goto open_error;
    }

    tmpCfg.bufSize = setup.buf.block.frag_size;
#ifdef HAVE_EXCEPTIONS
    _sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize];
#else
    _sampleBuffer = new int_least8_t[tmpCfg.bufSize];
#endif

    if (!_sampleBuffer)
    {
        _errorString = "AUDIO: Unable to allocate memory for sample buffers.";
        goto open_error;
    }

    // Setup internal Config
    _settings = tmpCfg;
    // Update the users settings
    getConfig (cfg);
    return _sampleBuffer;

open_error:
    if (_audioHandle != NULL)
    {
        close ();
    }

    perror ("ALSA");
return NULL;
}
Пример #19
0
static ALCboolean qsa_reset_playback(ALCdevice* device)
{
    qsa_data* data=(qsa_data*)device->ExtraData;
    int32_t format=-1;

    switch(device->FmtType)
    {
        case DevFmtByte:
             format=SND_PCM_SFMT_S8;
             break;
        case DevFmtUByte:
             format=SND_PCM_SFMT_U8;
             break;
        case DevFmtShort:
             format=SND_PCM_SFMT_S16_LE;
             break;
        case DevFmtUShort:
             format=SND_PCM_SFMT_U16_LE;
             break;
        case DevFmtInt:
             format=SND_PCM_SFMT_S32_LE;
             break;
        case DevFmtUInt:
             format=SND_PCM_SFMT_U32_LE;
             break;
        case DevFmtFloat:
             format=SND_PCM_SFMT_FLOAT_LE;
             break;
    }

    /* we actually don't want to block on writes */
    snd_pcm_nonblock_mode(data->pcmHandle, 1);
    /* Disable mmap to control data transfer to the audio device */
    snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP);
    snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS);

    // configure a sound channel
    memset(&data->cparams, 0, sizeof(data->cparams));
    data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK;
    data->cparams.mode=SND_PCM_MODE_BLOCK;
    data->cparams.start_mode=SND_PCM_START_FULL;
    data->cparams.stop_mode=SND_PCM_STOP_STOP;

    data->cparams.buf.block.frag_size=device->UpdateSize*
        ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
    data->cparams.buf.block.frags_max=device->NumUpdates;
    data->cparams.buf.block.frags_min=device->NumUpdates;

    data->cparams.format.interleave=1;
    data->cparams.format.rate=device->Frequency;
    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
    data->cparams.format.format=format;

    if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
    {
        int original_rate=data->cparams.format.rate;
        int original_voices=data->cparams.format.voices;
        int original_format=data->cparams.format.format;
        int it;
        int jt;

        for (it=0; it<1; it++)
        {
            /* Check for second pass */
            if (it==1)
            {
                original_rate=ratelist[0].rate;
                original_voices=channellist[0].channels;
                original_format=formatlist[0].format;
            }

            do {
                /* At first downgrade sample format */
                jt=0;
                do {
                    if (formatlist[jt].format==data->cparams.format.format)
                    {
                        data->cparams.format.format=formatlist[jt+1].format;
                        break;
                    }
                    if (formatlist[jt].format==0)
                    {
                        data->cparams.format.format=0;
                        break;
                    }
                    jt++;
                } while(1);

                if (data->cparams.format.format==0)
                {
                    data->cparams.format.format=original_format;

                    /* At secod downgrade sample rate */
                    jt=0;
                    do {
                        if (ratelist[jt].rate==data->cparams.format.rate)
                        {
                            data->cparams.format.rate=ratelist[jt+1].rate;
                            break;
                        }
                        if (ratelist[jt].rate==0)
                        {
                            data->cparams.format.rate=0;
                            break;
                        }
                        jt++;
                    } while(1);

                    if (data->cparams.format.rate==0)
                    {
                        data->cparams.format.rate=original_rate;
                        data->cparams.format.format=original_format;

                        /* At third downgrade channels number */
                        jt=0;
                        do {
                            if(channellist[jt].channels==data->cparams.format.voices)
                            {
                                data->cparams.format.voices=channellist[jt+1].channels;
                                break;
                            }
                            if (channellist[jt].channels==0)
                            {
                                data->cparams.format.voices=0;
                                break;
                            }
                           jt++;
                        } while(1);
                    }

                    if (data->cparams.format.voices==0)
                    {
                        break;
                    }
                }

                data->cparams.buf.block.frag_size=device->UpdateSize*
                    data->cparams.format.voices*
                    snd_pcm_format_width(data->cparams.format.format)/8;
                data->cparams.buf.block.frags_max=device->NumUpdates;
                data->cparams.buf.block.frags_min=device->NumUpdates;
                if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
                {
                    continue;
                }
                else
                {
                    break;
                }
            } while(1);

            if (data->cparams.format.voices!=0)
            {
                break;
            }
        }

        if (data->cparams.format.voices==0)
        {
            return ALC_FALSE;
        }
    }

    if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
    {
        return ALC_FALSE;
    }

    memset(&data->csetup, 0, sizeof(data->csetup));
    data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK;
    if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0)
    {
        return ALC_FALSE;
    }

    /* now fill back to the our AL device */
    device->Frequency=data->cparams.format.rate;

    switch (data->cparams.format.voices)
    {
        case 1:
             device->FmtChans=DevFmtMono;
             break;
        case 2:
             device->FmtChans=DevFmtStereo;
             break;
        case 4:
             device->FmtChans=DevFmtQuad;
             break;
        case 6:
             device->FmtChans=DevFmtX51;
             break;
        case 7:
             device->FmtChans=DevFmtX61;
             break;
        case 8:
             device->FmtChans=DevFmtX71;
             break;
        default:
             device->FmtChans=DevFmtMono;
             break;
    }

    switch (data->cparams.format.format)
    {
        case SND_PCM_SFMT_S8:
             device->FmtType=DevFmtByte;
             break;
        case SND_PCM_SFMT_U8:
             device->FmtType=DevFmtUByte;
             break;
        case SND_PCM_SFMT_S16_LE:
             device->FmtType=DevFmtShort;
             break;
        case SND_PCM_SFMT_U16_LE:
             device->FmtType=DevFmtUShort;
             break;
        case SND_PCM_SFMT_S32_LE:
             device->FmtType=DevFmtInt;
             break;
        case SND_PCM_SFMT_U32_LE:
             device->FmtType=DevFmtUInt;
             break;
        case SND_PCM_SFMT_FLOAT_LE:
             device->FmtType=DevFmtFloat;
             break;
        default:
             device->FmtType=DevFmtShort;
             break;
    }

    SetDefaultChannelOrder(device);

    device->UpdateSize=data->csetup.buf.block.frag_size/
        (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
    device->NumUpdates=data->csetup.buf.block.frags;

    data->size=data->csetup.buf.block.frag_size;
    data->buffer=malloc(data->size);
    if (!data->buffer)
    {
        return ALC_FALSE;
    }

    return ALC_TRUE;
}
Пример #20
0
int
main (int argc, char **argv)
{
    int     card = -1;
    int     dev = 0;
    snd_pcm_t *pcm_handle;
    FILE   *file;
    wave_hdr wav_header;
    int     samples;
    int     sample_rate;
    int     sample_channels;
    int     sample_bits;
    char   *sample_buffer;
    int     fragsize = -1;
    int     verbose = 0;

    int     rtn;
    int     final_return_code = -1;
    snd_pcm_channel_info_t pi;
    snd_mixer_t *mixer_handle;
    snd_mixer_group_t group;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;
    int     bsize, bytes_read, total_written = 0;
    fd_set  rfds, wfds;
    uint32_t voice_mask[] = { 0, 0, 0, 0 };
    snd_pcm_voice_conversion_t voice_conversion;
    int     voice_override = 0;
    int     num_frags = -1;
    char input_file[PATH_MAX];
    char cwd[PATH_MAX];
    screen_context_t screen_cxt;
    screen_window_t screen_win;
    screen_buffer_t screen_buf;
    int screen_fill_attribs[] = { SCREEN_BLIT_COLOR, COLOR_PURPLE, SCREEN_BLIT_END };
    int screen_dirty[4] = { 0, 0, 1024, 600 }; //start with sane default values

    int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
    int usage = SCREEN_USAGE_NATIVE;

    if (screen_create_context(&screen_cxt, 0) != 0)
    {
    	return err("failed to create context");
    }

    if (screen_create_window(&screen_win, screen_cxt) != 0)
    {
    	err("failed to create window");
    	goto fail1;
    }

    if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage) != 0)
    {
    	err("failed to set native usage mode");
    	goto fail2;
    }

    if (screen_create_window_buffers(screen_win, 1) != 0)
    {
    	err("failed to set native usage mode");
    	goto fail2;
    }

    if(screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf) != 0)
    {
    	err("failed to get screen buffer");
    	goto fail2;
    }

    if (screen_fill(screen_cxt, screen_buf, screen_fill_attribs) != 0) {
    	err("failed to fill the screen");
    	goto fail3;
    }

    if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, screen_dirty+2) != 0) {
    	err("failed to get window size");
    	goto fail3;
    }

    if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode) != 0)
    {
    	err("failed to set idle mode");
    	goto fail3;
    }

    if (screen_post_window(screen_win, screen_buf, 1, screen_dirty, 0) != 0) {
    	err("failed to post the window");
    	goto fail3;
    }

    if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0)
    {
        err ("device open");
        goto fail3;
    }

    getcwd(cwd, PATH_MAX);
    rtn = snprintf(input_file, PATH_MAX, "%s%s", cwd, WAV_RELATIVE_PATH);
    if (rtn > PATH_MAX - 1)
    {
    	err ("File name and path too long");
    	goto fail4;
    }

    if ((file = fopen (input_file, "r")) == 0)
    {
    	err ("File open failed");
    	goto fail4;
    }

    if (check_hdr (file) == -1) {
        err ("check_hdr failed");
        goto fail5;
    }

    samples = find_tag (file, "fmt ");
    fread (&wav_header, sizeof (wav_header), 1, file);
    fseek (file, (samples - sizeof (wave_hdr)), SEEK_CUR);

    sample_rate = ENDIAN_LE32 (wav_header.samples_per_sec);
    sample_channels = ENDIAN_LE16 (wav_header.channels);
    sample_bits = ENDIAN_LE16 (wav_header.bits_per_sample);

    printf ("SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels,
        sample_bits);

    /* disabling mmap is not actually required in this example but it is included to
     * demonstrate how it is used when it is required.
     */
    if ((rtn = snd_pcm_plugin_set_disable (pcm_handle, PLUGIN_DISABLE_MMAP)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    memset (&pp, 0, sizeof (pp));

    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_STOP;
    pp.buf.block.frag_size = pi.max_fragment_size;

    if (fragsize != -1)
    {
        pp.buf.block.frag_size = fragsize;
    }
    pp.buf.block.frags_max = num_frags;
    pp.buf.block.frags_min = 1;

    pp.format.interleave = 1;
    pp.format.rate = sample_rate;
    pp.format.voices = sample_channels;

    if (ENDIAN_LE16 (wav_header.format_tag) == 6)
        pp.format.format = SND_PCM_SFMT_A_LAW;
    else if (ENDIAN_LE16 (wav_header.format_tag) == 7)
        pp.format.format = SND_PCM_SFMT_MU_LAW;
    else if (sample_bits == 8)
        pp.format.format = SND_PCM_SFMT_U8;
    else if (sample_bits == 24)
        pp.format.format = SND_PCM_SFMT_S24;
    else
        pp.format.format = SND_PCM_SFMT_S16_LE;

    strcpy (pp.sw_mixer_subchn_name, "Wave playback channel");
    if ((rtn = snd_pcm_plugin_params (pcm_handle, &pp)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
        fprintf (stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    if (voice_override)
    {
        snd_pcm_plugin_get_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK,
            &voice_conversion);
        voice_conversion.matrix[0] = voice_mask[0];
        voice_conversion.matrix[1] = voice_mask[1];
        voice_conversion.matrix[2] = voice_mask[2];
        voice_conversion.matrix[3] = voice_mask[3];
        snd_pcm_plugin_set_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK,
            &voice_conversion);
    }

    memset (&setup, 0, sizeof (setup));
    memset (&group, 0, sizeof (group));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    setup.mixer_gid = &group.gid;

    if ((rtn = snd_pcm_plugin_setup (pcm_handle, &setup)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    printf ("Format %s \n", snd_pcm_get_format_name (setup.format.format));
    printf ("Frag Size %d \n", setup.buf.block.frag_size);
    printf ("Total Frags %d \n", setup.buf.block.frags);
    printf ("Rate %d \n", setup.format.rate);
    printf ("Voices %d \n", setup.format.voices);
    bsize = setup.buf.block.frag_size;

    if (group.gid.name[0] == 0)
    {
        fprintf (stderr, "Mixer Pcm Group [%s] Not Set \n", group.gid.name);
        goto fail5;
    }

    printf ("Mixer Pcm Group [%s]\n", group.gid.name);
    if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0)
    {
        fprintf (stderr, "snd_mixer_open failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    samples = find_tag (file, "data");
    sample_buffer = malloc (bsize);
    FD_ZERO (&rfds);
    FD_ZERO (&wfds);
    bytes_read = 1;
    while (total_written < samples && bytes_read > 0)
    {
        if (tcgetpgrp (0) == getpid ())
            FD_SET (STDIN_FILENO, &rfds);
        FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds);
        FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds);

        rtn = max (snd_mixer_file_descriptor (mixer_handle),
            snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK));

        if (select (rtn + 1, &rfds, &wfds, NULL, NULL) == -1)
        {
        	err ("select");
        	goto fail6;
        }

        if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds))
        {
            snd_pcm_channel_status_t status;
            int     written = 0;

            if ((bytes_read = fread (sample_buffer, 1, min (samples - total_written, bsize), file)) <= 0)
                continue;
            written = snd_pcm_plugin_write (pcm_handle, sample_buffer, bytes_read);
            if (verbose)
                printf ("bytes written = %d \n", written);

            if (written < bytes_read)
            {
                memset (&status, 0, sizeof (status));
                status.channel = SND_PCM_CHANNEL_PLAYBACK;
                if (snd_pcm_plugin_status (pcm_handle, &status) < 0)
                {
                    fprintf (stderr, "underrun: playback channel status error\n");
                    goto fail6;
                }

                if (status.status == SND_PCM_STATUS_READY ||
                    status.status == SND_PCM_STATUS_UNDERRUN)
                {
                    if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
                    {
                        fprintf (stderr, "underrun: playback channel prepare error\n");
                        goto fail6;
                    }
                }
                if (written < 0)
                    written = 0;
                written += snd_pcm_plugin_write (pcm_handle, sample_buffer + written, bytes_read - written);
            }
            total_written += written;
        }
    }

    bytes_read = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
    final_return_code = 0;

fail6:
    rtn = snd_mixer_close (mixer_handle);
fail5:
    fclose (file);
fail4:
    rtn = snd_pcm_close (pcm_handle);
fail3:
    screen_destroy_buffer(screen_buf);
fail2:
    screen_destroy_window(screen_win);
fail1:
    screen_destroy_context(screen_cxt);
    return final_return_code;
}
// Initialize audio and report back a few parameters of the channel
int setupAudio( )
{
    int error;
    snd_pcm_channel_info_t pi;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t ps;

    //if ((error = snd_pcm_open_name (&playback_handle, "pcmPreferred", SND_PCM_OPEN_PLAYBACK)) < 0) {
    if ((error = snd_pcm_open_name (&playback_handle, "tones", SND_PCM_OPEN_PLAYBACK)) < 0) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to open preferred audio driver\n");
        return -error;
    }

    sample_handle = snd_pcm_file_descriptor( playback_handle, SND_PCM_CHANNEL_PLAYBACK );

    if ((error = snd_pcm_plugin_set_disable (playback_handle, PLUGIN_DISABLE_MMAP)) < 0) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to disable mmap\n");
        snd_pcm_close(playback_handle);
        return -error;
    }

    if ((error = snd_pcm_plugin_set_enable (playback_handle, PLUGIN_ROUTING)) < 0)
    {
        slogf ( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "snd_pcm_plugin_set_enable failed: %s\n", snd_strerror (error));
        snd_pcm_close(playback_handle);
        return -error;
    }

    // Find what sample rate and format to use
    memset( &pi, 0, sizeof(pi) );
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((error = snd_pcm_channel_info (playback_handle, &pi)) < 0) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to get plugin info\n");
        snd_pcm_close(playback_handle);
        return -error;
    }

    // Initialize the playback channel
    memset(&pp, 0, sizeof(pp) );
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_STOP;
    pp.buf.block.frag_size = pi.max_fragment_size;
    pp.buf.block.frags_max = 3;
    pp.buf.block.frags_min = 1;
    pp.format.interleave = 1;
    pp.format.format =  SND_PCM_SFMT_S16_LE;
    pp.format.rate = 48000;
    pp.format.voices = 2;

    memset( &ps, 0, sizeof( ps ) );
    memset( &group, 0, sizeof( group ) );
    ps.channel = SND_PCM_CHANNEL_PLAYBACK;
    ps.mixer_gid = &group.gid;
    //strcpy(pp.sw_mixer_subchn_name, "Wave playback channel");
    strcpy(pp.sw_mixer_subchn_name, "voice_ringtone");

    if ((error = snd_pcm_plugin_params( playback_handle, &pp)) < 0)
    {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set plugin params\n");
        snd_pcm_close(playback_handle);
        return -error;
    }

    if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set prepare plugin\n");
        snd_pcm_close(playback_handle);
        return -error;
    }

    if ((error = snd_pcm_plugin_setup (playback_handle, &ps)) < 0) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to setup plugin\n");
        snd_pcm_close(playback_handle);
        return -error;
    }

    card = ps.mixer_card;
    device = ps.mixer_device;

    if( audioman_handle ) {
        if ((error = snd_pcm_set_audioman_handle (playback_handle, audioman_handle)) < 0) {
            slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set audioman handle \n");
            snd_pcm_close(playback_handle);
            return -error;
        }
    }

    sample_frequency = ps.format.rate;
    frag_samples = ps.buf.block.frag_size / 4;
    frame_size = ps.buf.block.frag_size;
    format = pp.format.format;
/*
    // Only support 16-bit samples for now
    frag_buffer = malloc( ps.buf.block.frag_size * 2 );
    if( frag_buffer == NULL ) {
        slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to alloc frag buffer\n");
        snd_pcm_close(playback_handle);
        return ENOMEM;
    }
*/
	fprintf (stderr,"Playback Format %s card = %d\n", snd_pcm_get_format_name (ps.format.format),card);
	fprintf (stderr,"Playback preferred frame_size %d \n", pi.max_fragment_size);
	fprintf (stderr,"Playback frame_size %d \n", ps.buf.block.frag_size);
	fprintf (stderr,"Playback frame_samples %d \n", frag_samples);
	fprintf (stderr,"Playback Rate %d \n", ps.format.rate);

	if (group.gid.name[0] == 0)
	{
		fprintf (stderr,"Playback Mixer Pcm Group [%s] Not Set \n", group.gid.name);
        return -1;
	}
	fprintf (stderr, "Playback Mixer Pcm Group [%s]\n", group.gid.name);

    return EOK;
}