コード例 #1
0
ファイル: alsa_qsa.c プロジェクト: DSkywalk/RetroArch
static void alsa_qsa_set_nonblock_state(void *data, bool state)
{
   alsa_t *alsa = (alsa_t*)data;

   int err;

   if((err = snd_pcm_nonblock_mode(alsa->pcm, state)) < 0)
   {
      RARCH_ERR("Can't set blocking mode to %d: %s\n", state,
            snd_strerror(err));
      return;
   }

   alsa->nonblock = state;
}
コード例 #2
0
ファイル: alsa_qsa.c プロジェクト: DSkywalk/RetroArch
static void *alsa_qsa_init(const char *device,
      unsigned rate, unsigned latency, unsigned block_frames,
      unsigned *new_rate)
{
   int err, card, dev, i;
   snd_pcm_channel_info_t pi;
   snd_pcm_channel_params_t params = {0};
   snd_pcm_channel_setup_t setup   = {0};
   alsa_t *alsa                    = (alsa_t*)calloc(1, sizeof(alsa_t));
   if (!alsa)
      return NULL;

   (void)device;
   (void)rate;
   (void)latency;

   if ((err = snd_pcm_open_preferred(&alsa->pcm, &card, &dev,
               SND_PCM_OPEN_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Audio open error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if((err = snd_pcm_nonblock_mode(alsa->pcm, 1)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Can't set blocking mode: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&pi, 0, sizeof(pi));
   pi.channel = SND_PCM_CHANNEL_PLAYBACK;
   if ((err = snd_pcm_channel_info(alsa->pcm, &pi)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: snd_pcm_channel_info failed: %s\n",
            snd_strerror(err));
      goto error;
   }

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

   params.channel = SND_PCM_CHANNEL_PLAYBACK;
   params.mode = SND_PCM_MODE_BLOCK;

   params.format.interleave = 1;
   params.format.format = SND_PCM_SFMT_S16_LE;
   params.format.rate = DEFAULT_RATE;
   params.format.voices = 2;

   params.start_mode = SND_PCM_START_FULL;
   params.stop_mode = SND_PCM_STOP_STOP;

   params.buf.block.frag_size = pi.max_fragment_size;
   params.buf.block.frags_min = 2;
   params.buf.block.frags_max = 8;

   RARCH_LOG("Fragment size: %d\n", params.buf.block.frag_size);
   RARCH_LOG("Min Fragment size: %d\n", params.buf.block.frags_min);
   RARCH_LOG("Max Fragment size: %d\n", params.buf.block.frags_max);

   if ((err = snd_pcm_channel_params(alsa->pcm, &params)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   setup.channel = SND_PCM_CHANNEL_PLAYBACK;

   if ((err = snd_pcm_channel_setup(alsa->pcm, &setup)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Read Back Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if (block_frames)
      alsa->buf_size = block_frames * 4;
   else
      alsa->buf_size = next_pow2(32 * latency);

   RARCH_LOG("[ALSA QSA]: buffer size: %u bytes\n", alsa->buf_size);

   alsa->buf_count = (latency * 4 * rate + 500) / 1000;
   alsa->buf_count = (alsa->buf_count + alsa->buf_size / 2) / alsa->buf_size;

   if ((err = snd_pcm_channel_prepare(alsa->pcm,
               SND_PCM_CHANNEL_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Prepare Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   alsa->buffer = (uint8_t**)calloc(sizeof(uint8_t*), alsa->buf_count);
   if (!alsa->buffer)
      goto error;

   alsa->buffer_chunk = (uint8_t*)calloc(alsa->buf_count, alsa->buf_size);
   if (!alsa->buffer_chunk)
      goto error;

   for (i = 0; i < alsa->buf_count; i++)
      alsa->buffer[i] = alsa->buffer_chunk + i * alsa->buf_size;

   alsa->has_float = false;
   alsa->can_pause = true;
   RARCH_LOG("[ALSA QSA]: Can pause: %s.\n",
         alsa->can_pause ? "yes" : "no");

   return alsa;

error:
   return (void*)-1;
}
コード例 #3
0
ファイル: alsapmo.cpp プロジェクト: mayhem/freeamp
Error AlsaPMO::Init(OutputInfo* info) 
{
    int                      err;
    snd_pcm_channel_params_t params;

    m_properlyInitialized = false;
    if (!info) 
    {
        info = myInfo;
    } 
    else 
    {
        // got info, so this is the beginning...
        m_iDataSize = info->max_buffer_size;

        err=snd_pcm_open(&m_handle, m_iCard, m_iDevice, 
                         SND_PCM_OPEN_PLAYBACK);
        if (err < 0)
        {
            ReportError("Audio device is busy. Please make sure that "
                        "another program is not using the device.");
            return (Error)pmoError_DeviceOpenFailed;
        }

        snd_pcm_nonblock_mode(m_handle, 1);
    }

    // configure the device:
    m_channels=info->number_of_channels;
    m_rate=info->samples_per_second;

    memset(&params, 0, sizeof(params)); 
    params.format.format = SND_PCM_SFMT_S16_LE;
    params.format.interleave = 1;
    params.format.voices = m_channels;
    params.format.rate = info->samples_per_second;
    params.channel = SND_PCM_CHANNEL_PLAYBACK;
    params.mode = SND_PCM_MODE_BLOCK;
    params.start_mode = SND_PCM_START_DATA;
    params.stop_mode = SND_PCM_STOP_STOP;
    params.buf.block.frag_size = m_iDataSize;
    params.buf.block.frags_max = 32;
    params.buf.block.frags_min = 1;

    err = snd_pcm_channel_params(m_handle, &params);
    if (err < 0)
    {
        ReportError("Cannot initialized audio device.");
        return (Error)pmoError_DeviceOpenFailed;
    }
    err = snd_pcm_channel_prepare(m_handle, SND_PCM_CHANNEL_PLAYBACK);
    if (err < 0)
    {
        ReportError("Cannot initialized audio device.");
        return (Error)pmoError_DeviceOpenFailed;
    }

    memcpy(myInfo, info, sizeof(OutputInfo));

    snd_pcm_channel_setup_t aInfo;
    aInfo.channel = SND_PCM_CHANNEL_PLAYBACK;
    err = snd_pcm_channel_setup(m_handle,&aInfo);
    if (err < 0)
    {
        ReportError("Cannot initialized audio device.");
        return (Error)pmoError_DeviceOpenFailed;
    }

    m_iOutputBufferSize = aInfo.buf.block.frag_size * aInfo.buf.block.frags;
    m_iBytesPerSample = info->number_of_channels * (info->bits_per_sample / 8);



    m_properlyInitialized = true;
    return kError_NoErr;
}
コード例 #4
0
ファイル: SDL_nto_audio.c プロジェクト: wwzbwwzb/fbdri
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);
}
コード例 #5
0
ファイル: qsa.c プロジェクト: Sponk/NeoEditor
static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
{
    qsa_data *data;
    int card, dev;
    int format=-1;
    int status;

    data=(qsa_data*)calloc(1, sizeof(qsa_data));
    if (data==NULL)
    {
        return ALC_OUT_OF_MEMORY;
    }

    if(!deviceName)
        deviceName = qsaDevice;

    if(strcmp(deviceName, qsaDevice) == 0)
        status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
    else
    {
        const DevMap *iter;

        if(VECTOR_SIZE(CaptureNameMap) == 0)
            deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);

#define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
        VECTOR_FIND_IF(iter, const DevMap, CaptureNameMap, MATCH_DEVNAME);
#undef MATCH_DEVNAME
        if(iter == VECTOR_ITER_END(CaptureNameMap))
        {
            free(data);
            return ALC_INVALID_DEVICE;
        }

        status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_CAPTURE);
    }

    if(status < 0)
    {
        free(data);
        return ALC_INVALID_DEVICE;
    }

    data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
    if(data->audio_fd < 0)
    {
        snd_pcm_close(data->pcmHandle);
        free(data);
        return ALC_INVALID_DEVICE;
    }

    al_string_copy_cstr(&device->DeviceName, deviceName);
    device->ExtraData = data;

    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 reads */
    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);

    /* configure a sound channel */
    memset(&data->cparams, 0, sizeof(data->cparams));
    data->cparams.mode=SND_PCM_MODE_BLOCK;
    data->cparams.channel=SND_PCM_CHANNEL_CAPTURE;
    data->cparams.start_mode=SND_PCM_START_GO;
    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)
    {
        snd_pcm_close(data->pcmHandle);
        free(data);
        device->ExtraData=NULL;

        return ALC_INVALID_VALUE;
    }

    return ALC_NO_ERROR;
}
コード例 #6
0
ファイル: qsa.c プロジェクト: Sponk/NeoEditor
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;
}
コード例 #7
0
ファイル: audio_driver_bb10.cpp プロジェクト: Alex-doc/godot
void AudioDriverBB10::thread_func(void *p_udata) {

	AudioDriverBB10 *ad = (AudioDriverBB10 *)p_udata;

	int channels = speaker_mode;
	int frame_count = ad->sample_buf_count / channels;
	int bytes_out = frame_count * channels * 2;

	while (!ad->exit_thread) {

		if (!ad->active) {

			for (int i = 0; i < ad->sample_buf_count; i++) {

				ad->samples_out[i] = 0;
			};
		} else {

			ad->lock();

			ad->audio_server_process(frame_count, ad->samples_in);

			ad->unlock();

			for (int i = 0; i < frame_count * channels; i++) {

				ad->samples_out[i] = ad->samples_in[i] >> 16;
			}
		};

		int todo = bytes_out;
		int total = 0;

		while (todo) {

			uint8_t *src = (uint8_t *)ad->samples_out;
			int wrote = snd_pcm_plugin_write(ad->pcm_handle, (void *)(src + total), todo);
			if (wrote < 0) {
				// error?
				break;
			};
			total += wrote;
			todo -= wrote;
			if (wrote < todo) {
				if (ad->thread_exited) {
					break;
				};
				printf("pcm_write underrun %i, errno %i\n", (int)ad->thread_exited, errno);
				snd_pcm_channel_status_t status;
				zeromem(&status, sizeof(status));
				// put in non-blocking mode
				snd_pcm_nonblock_mode(ad->pcm_handle, 1);
				status.channel = SND_PCM_CHANNEL_PLAYBACK;
				int ret = snd_pcm_plugin_status(ad->pcm_handle, &status);
				//printf("status return %i, %i, %i, %i, %i\n", ret, errno, status.status, SND_PCM_STATUS_READY, SND_PCM_STATUS_UNDERRUN);
				snd_pcm_nonblock_mode(ad->pcm_handle, 0);
				if (ret < 0) {
					break;
				};
				if (status.status == SND_PCM_STATUS_READY ||
						status.status == SND_PCM_STATUS_UNDERRUN) {
					snd_pcm_plugin_prepare(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
				} else {
					break;
				};
			};
		};
	};

	snd_pcm_plugin_flush(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);

	ad->thread_exited = true;
	printf("**************** audio thread exit\n");
};
コード例 #8
0
ファイル: io-audio.c プロジェクト: CarnyPriest/SAMbuild
/* 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;
}
コード例 #9
0
int ao_plugin_open(ao_device *device, ao_sample_format *format)
{
	ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;

	snd_pcm_channel_params_t param;
	int err;

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

	param.channel = SND_PCM_CHANNEL_PLAYBACK;
	param.mode = SND_PCM_MODE_BLOCK;

	param.format.interleave = 1;

	switch (format->bits) {
	case 8  : param.format.format = SND_PCM_SFMT_S8;
		  break;
        case 16 : param.format.format = 
		    device->client_byte_format == AO_FMT_BIG ?
		    SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_S16_LE;
	          device->driver_byte_format = device->client_byte_format;
		  break;
	default : return 0;
	}

	if (format->channels == 1 || format->channels == 2)
		param.format.voices = format->channels;
	else
		return 0;

	/* Finish filling in the parameter structure */
	param.format.rate = format->rate;

	param.start_mode = SND_PCM_START_FULL;
	
	param.stop_mode = SND_PCM_STOP_STOP;

	param.buf.block.frag_size = internal->buf_size;
	param.buf.block.frags_min = 1;
	param.buf.block.frags_max = 8;

	internal->buf = malloc(internal->buf_size);
	internal->buf_end = 0;
	if (internal->buf == NULL)
	  return 0;  /* Could not alloc swap buffer */


	/* Open the ALSA device */
	err = snd_pcm_open(&(internal->pcm_handle), 
			   internal->card, 
			   internal->dev,
			   SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK);
	if (err < 0) {
		free(internal->buf);
		return 0;
	}

	err = snd_pcm_channel_params(internal->pcm_handle, &param);

	if (err < 0) {
		snd_pcm_close(internal->pcm_handle);
		free(internal->buf);
		return 0;
	}

	snd_pcm_nonblock_mode(internal->pcm_handle, 0);
	snd_pcm_channel_prepare(internal->pcm_handle, 
				SND_PCM_CHANNEL_PLAYBACK);

	return 1;
}