Пример #1
0
static int load_ambdec_speakers(AmbDecConf *conf, FILE *f, char **buffer, size_t *maxlen, char **saveptr)
{
    ALuint cur = 0;
    while(cur < conf->NumSpeakers)
    {
        const char *cmd = my_strtok_r(NULL, " \t", saveptr);
        if(!cmd)
        {
            char *line = read_clipped_line(f, buffer, maxlen);
            if(!line)
            {
                ERR("Unexpected end of file\n");
                return 0;
            }
            cmd = my_strtok_r(line, " \t", saveptr);
        }

        if(strcmp(cmd, "add_spkr") == 0)
        {
            const char *name = my_strtok_r(NULL, " \t", saveptr);
            const char *dist = my_strtok_r(NULL, " \t", saveptr);
            const char *az = my_strtok_r(NULL, " \t", saveptr);
            const char *elev = my_strtok_r(NULL, " \t", saveptr);
            const char *conn = my_strtok_r(NULL, " \t", saveptr);

            if(!name) WARN("Name not specified for speaker %u\n", cur+1);
            else al_string_copy_cstr(&conf->Speakers[cur].Name, name);
            if(!dist) WARN("Distance not specified for speaker %u\n", cur+1);
            else read_float(&conf->Speakers[cur].Distance, dist);
            if(!az) WARN("Azimuth not specified for speaker %u\n", cur+1);
            else read_float(&conf->Speakers[cur].Azimuth, az);
            if(!elev) WARN("Elevation not specified for speaker %u\n", cur+1);
            else read_float(&conf->Speakers[cur].Elevation, elev);
            if(!conn) TRACE("Connection not specified for speaker %u\n", cur+1);
            else al_string_copy_cstr(&conf->Speakers[cur].Connection, conn);

            cur++;
        }
        else
        {
            ERR("Unexpected speakers command: %s\n", cmd);
            return 0;
        }

        cmd = my_strtok_r(NULL, " \t", saveptr);
        if(cmd)
        {
            ERR("Unexpected junk on line: %s\n", cmd);
            return 0;
        }
    }

    return 1;
}
Пример #2
0
static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
    sndio_data *data;

    if(!deviceName)
        deviceName = sndio_device;
    else if(strcmp(deviceName, sndio_device) != 0)
        return ALC_INVALID_VALUE;

    data = calloc(1, sizeof(*data));
    data->killNow = 0;

    data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
    if(data->sndHandle == NULL)
    {
        free(data);
        ERR("Could not open device\n");
        return ALC_INVALID_VALUE;
    }

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

    return ALC_NO_ERROR;
}
Пример #3
0
static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName)
{
    osl_data *data = NULL;
    SLresult result;

    if(!deviceName)
        deviceName = opensl_device;
    else if(strcmp(deviceName, opensl_device) != 0)
        return ALC_INVALID_VALUE;

    data = calloc(1, sizeof(*data));
    if(!data)
        return ALC_OUT_OF_MEMORY;

    // create engine
    result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL);
    PRINTERR(result, "slCreateEngine");
    if(SL_RESULT_SUCCESS == result)
    {
        result = VCALL(data->engineObject,Realize)(SL_BOOLEAN_FALSE);
        PRINTERR(result, "engine->Realize");
    }
    if(SL_RESULT_SUCCESS == result)
    {
        result = VCALL(data->engineObject,GetInterface)(SL_IID_ENGINE, &data->engine);
        PRINTERR(result, "engine->GetInterface");
    }
    if(SL_RESULT_SUCCESS == result)
    {
        result = VCALL(data->engine,CreateOutputMix)(&data->outputMix, 0, NULL, NULL);
        PRINTERR(result, "engine->CreateOutputMix");
    }
    if(SL_RESULT_SUCCESS == result)
    {
        result = VCALL(data->outputMix,Realize)(SL_BOOLEAN_FALSE);
        PRINTERR(result, "outputMix->Realize");
    }

    if(SL_RESULT_SUCCESS != result)
    {
        if(data->outputMix != NULL)
            VCALL0(data->outputMix,Destroy)();
        data->outputMix = NULL;

        if(data->engineObject != NULL)
            VCALL0(data->engineObject,Destroy)();
        data->engineObject = NULL;
        data->engine = NULL;

        free(data);
        return ALC_INVALID_VALUE;
    }

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

    return ALC_NO_ERROR;
}
Пример #4
0
static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName)
{
    qsa_data *data;
    int card, dev;
    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_PLAYBACK);
    else
    {
        const DevMap *iter;

        if(VECTOR_SIZE(DeviceNameMap) == 0)
            deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);

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

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

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

    data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
    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;

    return ALC_NO_ERROR;
}
Пример #5
0
static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
    ComponentDescription desc;
    Component comp;
    ca_data *data;
    OSStatus err;

    if(!deviceName)
        deviceName = ca_device;
    else if(strcmp(deviceName, ca_device) != 0)
        return ALC_INVALID_VALUE;

    /* open the default output unit */
    desc.componentType = kAudioUnitType_Output;
    desc.componentSubType = kAudioUnitSubType_DefaultOutput;
    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    desc.componentFlags = 0;
    desc.componentFlagsMask = 0;

    comp = FindNextComponent(NULL, &desc);
    if(comp == NULL)
    {
        ERR("FindNextComponent failed\n");
        return ALC_INVALID_VALUE;
    }

    data = calloc(1, sizeof(*data));

    err = OpenAComponent(comp, &data->audioUnit);
    if(err != noErr)
    {
        ERR("OpenAComponent failed\n");
        free(data);
        return ALC_INVALID_VALUE;
    }

    /* init and start the default audio unit... */
    err = AudioUnitInitialize(data->audioUnit);
    if(err != noErr)
    {
        ERR("AudioUnitInitialize failed\n");
        CloseComponent(data->audioUnit);
        free(data);
        return ALC_INVALID_VALUE;
    }

    al_string_copy_cstr(&device->DeviceName, deviceName);
    device->ExtraData = data;
    return ALC_NO_ERROR;
}
Пример #6
0
static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
{
    vector_DevMap *devices = data;
    OLECHAR *guidstr = NULL;
    DevMap entry;
    HRESULT hr;
    int count;

    if(!guid)
        return TRUE;

    AL_STRING_INIT(entry.name);

    count = 0;
    while(1)
    {
        const DevMap *iter;

        al_string_copy_cstr(&entry.name, DEVNAME_HEAD);
        al_string_append_wcstr(&entry.name, desc);
        if(count != 0)
        {
            char str[64];
            snprintf(str, sizeof(str), " #%d", count+1);
            al_string_append_cstr(&entry.name, str);
        }

#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0)
        VECTOR_FIND_IF(iter, const DevMap, *devices, MATCH_ENTRY);
        if(iter == VECTOR_END(*devices)) break;
#undef MATCH_ENTRY
        count++;
    }
    entry.guid = *guid;

    hr = StringFromCLSID(guid, &guidstr);
    if(SUCCEEDED(hr))
    {
        TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(entry.name), guidstr);
        CoTaskMemFree(guidstr);
    }

    VECTOR_PUSH_BACK(*devices, entry);

    return TRUE;
}
Пример #7
0
static void ProbeCaptureDevices(void)
{
    ALuint numdevs;
    ALuint i;

    clear_devlist(&CaptureDevices);

    numdevs = waveInGetNumDevs();
    VECTOR_RESERVE(CaptureDevices, numdevs);
    for(i = 0;i < numdevs;i++)
    {
        WAVEINCAPSW WaveCaps;
        const al_string *iter;
        al_string dname;

        AL_STRING_INIT(dname);
        if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
        {
            ALuint count = 0;
            while(1)
            {
                al_string_copy_cstr(&dname, DEVNAME_HEAD);
                al_string_append_wcstr(&dname, WaveCaps.szPname);
                if(count != 0)
                {
                    char str[64];
                    snprintf(str, sizeof(str), " #%d", count+1);
                    al_string_append_cstr(&dname, str);
                }
                count++;

#define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0)
                VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_ENTRY);
                if(iter == VECTOR_END(CaptureDevices)) break;
#undef MATCH_ENTRY
            }

            TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
        }
        VECTOR_PUSH_BACK(CaptureDevices, dname);
    }
}
Пример #8
0
static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
    AudioStreamBasicDescription requestedFormat;  // The application requested format
    AudioStreamBasicDescription hardwareFormat;   // The hardware format
    AudioStreamBasicDescription outputFormat;     // The AudioUnit output format
    AURenderCallbackStruct input;
    ComponentDescription desc;
    AudioDeviceID inputDevice;
    UInt32 outputFrameCount;
    UInt32 propertySize;
    UInt32 enableIO;
    Component comp;
    ca_data *data;
    OSStatus err;

    desc.componentType = kAudioUnitType_Output;
    desc.componentSubType = kAudioUnitSubType_HALOutput;
    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    desc.componentFlags = 0;
    desc.componentFlagsMask = 0;

    // Search for component with given description
    comp = FindNextComponent(NULL, &desc);
    if(comp == NULL)
    {
        ERR("FindNextComponent failed\n");
        return ALC_INVALID_VALUE;
    }

    data = calloc(1, sizeof(*data));
    device->ExtraData = data;

    // Open the component
    err = OpenAComponent(comp, &data->audioUnit);
    if(err != noErr)
    {
        ERR("OpenAComponent failed\n");
        goto error;
    }

    // Turn off AudioUnit output
    enableIO = 0;
    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
    if(err != noErr)
    {
        ERR("AudioUnitSetProperty failed\n");
        goto error;
    }

    // Turn on AudioUnit input
    enableIO = 1;
    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
    if(err != noErr)
    {
        ERR("AudioUnitSetProperty failed\n");
        goto error;
    }

    // Get the default input device
    propertySize = sizeof(AudioDeviceID);
    err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice);
    if(err != noErr)
    {
        ERR("AudioHardwareGetProperty failed\n");
        goto error;
    }

    if(inputDevice == kAudioDeviceUnknown)
    {
        ERR("No input device found\n");
        goto error;
    }

    // Track the input device
    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
    if(err != noErr)
    {
        ERR("AudioUnitSetProperty failed\n");
        goto error;
    }

    // set capture callback
    input.inputProc = ca_capture_callback;
    input.inputProcRefCon = device;

    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
    if(err != noErr)
    {
        ERR("AudioUnitSetProperty failed\n");
        goto error;
    }

    // Initialize the device
    err = AudioUnitInitialize(data->audioUnit);
    if(err != noErr)
    {
        ERR("AudioUnitInitialize failed\n");
        goto error;
    }

    // Get the hardware format
    propertySize = sizeof(AudioStreamBasicDescription);
    err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
    if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription))
    {
        ERR("AudioUnitGetProperty failed\n");
        goto error;
    }

    // Set up the requested format description
    switch(device->FmtType)
    {
        case DevFmtUByte:
            requestedFormat.mBitsPerChannel = 8;
            requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
            break;
        case DevFmtShort:
            requestedFormat.mBitsPerChannel = 16;
            requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
            break;
        case DevFmtInt:
            requestedFormat.mBitsPerChannel = 32;
            requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
            break;
        case DevFmtFloat:
            requestedFormat.mBitsPerChannel = 32;
            requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
            break;
        case DevFmtByte:
        case DevFmtUShort:
        case DevFmtUInt:
            ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
            goto error;
    }

    switch(device->FmtChans)
    {
        case DevFmtMono:
            requestedFormat.mChannelsPerFrame = 1;
            break;
        case DevFmtStereo:
            requestedFormat.mChannelsPerFrame = 2;
            break;

        case DevFmtQuad:
        case DevFmtX51:
        case DevFmtX51Side:
        case DevFmtX61:
        case DevFmtX71:
            ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
            goto error;
    }

    requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8;
    requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame;
    requestedFormat.mSampleRate = device->Frequency;
    requestedFormat.mFormatID = kAudioFormatLinearPCM;
    requestedFormat.mReserved = 0;
    requestedFormat.mFramesPerPacket = 1;

    // save requested format description for later use
    data->format = requestedFormat;
    data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);

    // Use intermediate format for sample rate conversion (outputFormat)
    // Set sample rate to the same as hardware for resampling later
    outputFormat = requestedFormat;
    outputFormat.mSampleRate = hardwareFormat.mSampleRate;

    // Determine sample rate ratio for resampling
    data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency;

    // The output format should be the requested format, but using the hardware sample rate
    // This is because the AudioUnit will automatically scale other properties, except for sample rate
    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
    if(err != noErr)
    {
        ERR("AudioUnitSetProperty failed\n");
        goto error;
    }

    // Set the AudioUnit output format frame count
    outputFrameCount = device->UpdateSize * data->sampleRateRatio;
    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
    if(err != noErr)
    {
        ERR("AudioUnitSetProperty failed: %d\n", err);
        goto error;
    }

    // Set up sample converter
    err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter);
    if(err != noErr)
    {
        ERR("AudioConverterNew failed: %d\n", err);
        goto error;
    }

    // Create a buffer for use in the resample callback
    data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio);

    // Allocate buffer for the AudioUnit output
    data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio);
    if(data->bufferList == NULL)
        goto error;

    data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates);
    if(data->ring == NULL)
        goto error;

    al_string_copy_cstr(&device->DeviceName, deviceName);

    return ALC_NO_ERROR;

error:
    DestroyRingBuffer(data->ring);
    free(data->resampleBuffer);
    destroy_buffer_list(data->bufferList);

    if(data->audioConverter)
        AudioConverterDispose(data->audioConverter);
    if(data->audioUnit)
        CloseComponent(data->audioUnit);

    free(data);
    device->ExtraData = NULL;

    return ALC_INVALID_VALUE;
}
Пример #9
0
static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
{
    const char *main_prefix = "plughw:";
    snd_ctl_t *handle;
    snd_ctl_card_info_t *info;
    snd_pcm_info_t *pcminfo;
    int card, err, dev;
    DevMap entry;

    clear_devlist(DeviceList);

    snd_ctl_card_info_malloc(&info);
    snd_pcm_info_malloc(&pcminfo);

    AL_STRING_INIT(entry.name);
    AL_STRING_INIT(entry.device_name);
    al_string_copy_cstr(&entry.name, alsaDevice);
    al_string_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
                                                           "device" : "capture", "default"));
    VECTOR_PUSH_BACK(*DeviceList, entry);

    card = -1;
    if((err=snd_card_next(&card)) < 0)
        ERR("Failed to find a card: %s\n", snd_strerror(err));
    ConfigValueStr(NULL, "alsa", prefix_name(stream), &main_prefix);
    while(card >= 0)
    {
        const char *card_prefix = main_prefix;
        const char *cardname, *cardid;
        char name[256];

        snprintf(name, sizeof(name), "hw:%d", card);
        if((err = snd_ctl_open(&handle, name, 0)) < 0)
        {
            ERR("control open (hw:%d): %s\n", card, snd_strerror(err));
            goto next_card;
        }
        if((err = snd_ctl_card_info(handle, info)) < 0)
        {
            ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err));
            snd_ctl_close(handle);
            goto next_card;
        }

        cardname = snd_ctl_card_info_get_name(info);
        cardid = snd_ctl_card_info_get_id(info);

        snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
        ConfigValueStr(NULL, "alsa", name, &card_prefix);

        dev = -1;
        while(1)
        {
            const char *device_prefix = card_prefix;
            const char *devname;
            char device[128];

            if(snd_ctl_pcm_next_device(handle, &dev) < 0)
                ERR("snd_ctl_pcm_next_device failed\n");
            if(dev < 0)
                break;

            snd_pcm_info_set_device(pcminfo, dev);
            snd_pcm_info_set_subdevice(pcminfo, 0);
            snd_pcm_info_set_stream(pcminfo, stream);
            if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
                if(err != -ENOENT)
                    ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err));
                continue;
            }

            devname = snd_pcm_info_get_name(pcminfo);

            snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
            ConfigValueStr(NULL, "alsa", name, &device_prefix);

            snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
                        cardname, devname, cardid, dev);
            snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
                        device_prefix, cardid, dev);

            TRACE("Got device \"%s\", \"%s\"\n", name, device);
            AL_STRING_INIT(entry.name);
            AL_STRING_INIT(entry.device_name);
            al_string_copy_cstr(&entry.name, name);
            al_string_copy_cstr(&entry.device_name, device);
            VECTOR_PUSH_BACK(*DeviceList, entry);
        }
        snd_ctl_close(handle);
    next_card:
        if(snd_card_next(&card) < 0) {
            ERR("snd_card_next failed\n");
            break;
        }
    }

    snd_pcm_info_free(pcminfo);
    snd_ctl_card_info_free(info);
}
Пример #10
0
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;
}
Пример #11
0
static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
    ALuint frame_size;
    pa_data *data;
    PaError err;

    if(!deviceName)
        deviceName = pa_device;
    else if(strcmp(deviceName, pa_device) != 0)
        return ALC_INVALID_VALUE;

    data = (pa_data*)calloc(1, sizeof(pa_data));
    if(data == NULL)
        return ALC_OUT_OF_MEMORY;

    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
    data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
    if(data->ring == NULL)
        goto error;

    data->params.device = -1;
    if(!ConfigValueInt(NULL, "port", "capture", &data->params.device) ||
       data->params.device < 0)
        data->params.device = Pa_GetDefaultInputDevice();
    data->params.suggestedLatency = 0.0f;
    data->params.hostApiSpecificStreamInfo = NULL;

    switch(device->FmtType)
    {
        case DevFmtByte:
            data->params.sampleFormat = paInt8;
            break;
        case DevFmtUByte:
            data->params.sampleFormat = paUInt8;
            break;
        case DevFmtShort:
            data->params.sampleFormat = paInt16;
            break;
        case DevFmtInt:
            data->params.sampleFormat = paInt32;
            break;
        case DevFmtFloat:
            data->params.sampleFormat = paFloat32;
            break;
        case DevFmtUInt:
        case DevFmtUShort:
            ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
            goto error;
    }
    data->params.channelCount = ChannelsFromDevFmt(device->FmtChans);

    err = Pa_OpenStream(&data->stream, &data->params, NULL, device->Frequency,
                        paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
    if(err != paNoError)
    {
        ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
        goto error;
    }

    al_string_copy_cstr(&device->DeviceName, deviceName);

    device->ExtraData = data;
    return ALC_NO_ERROR;

error:
    DestroyRingBuffer(data->ring);
    free(data);
    return ALC_INVALID_VALUE;
}
Пример #12
0
static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
    pa_data *data;
    PaError err;

    if(!deviceName)
        deviceName = pa_device;
    else if(strcmp(deviceName, pa_device) != 0)
        return ALC_INVALID_VALUE;

    data = (pa_data*)calloc(1, sizeof(pa_data));
    data->update_size = device->UpdateSize;

    data->params.device = -1;
    if(!ConfigValueInt(NULL, "port", "device", &data->params.device) ||
       data->params.device < 0)
        data->params.device = Pa_GetDefaultOutputDevice();
    data->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
                                    (float)device->Frequency;
    data->params.hostApiSpecificStreamInfo = NULL;

    data->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);

    switch(device->FmtType)
    {
        case DevFmtByte:
            data->params.sampleFormat = paInt8;
            break;
        case DevFmtUByte:
            data->params.sampleFormat = paUInt8;
            break;
        case DevFmtUShort:
            /* fall-through */
        case DevFmtShort:
            data->params.sampleFormat = paInt16;
            break;
        case DevFmtUInt:
            /* fall-through */
        case DevFmtInt:
            data->params.sampleFormat = paInt32;
            break;
        case DevFmtFloat:
            data->params.sampleFormat = paFloat32;
            break;
    }

retry_open:
    err = Pa_OpenStream(&data->stream, NULL, &data->params, device->Frequency,
                        device->UpdateSize, paNoFlag, pa_callback, device);
    if(err != paNoError)
    {
        if(data->params.sampleFormat == paFloat32)
        {
            data->params.sampleFormat = paInt16;
            goto retry_open;
        }
        ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
        free(data);
        return ALC_INVALID_VALUE;
    }

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

    return ALC_NO_ERROR;
}
Пример #13
0
int ambdec_load(AmbDecConf *conf, const char *fname)
{
    char *buffer = NULL;
    size_t maxlen = 0;
    char *line;
    FILE *f;

    f = al_fopen(fname, "r");
    if(!f)
    {
        ERR("Failed to open: %s\n", fname);
        return 0;
    }

    while((line=read_clipped_line(f, &buffer, &maxlen)) != NULL)
    {
        char *saveptr;
        char *command;

        command = my_strtok_r(line, "/ \t", &saveptr);
        if(!command)
        {
            ERR("Malformed line: %s\n", line);
            goto fail;
        }

        if(strcmp(command, "description") == 0)
        {
            char *value = my_strtok_r(NULL, "", &saveptr);
            al_string_copy_cstr(&conf->Description, lstrip(value));
        }
        else if(strcmp(command, "version") == 0)
        {
            line = my_strtok_r(NULL, "", &saveptr);
            line = read_uint(&conf->Version, line, 10);
            if(line && *line != '\0')
            {
                ERR("Extra junk after version: %s\n", line);
                goto fail;
            }
            if(conf->Version != 3)
            {
                ERR("Unsupported version: %u\n", conf->Version);
                goto fail;
            }
        }
        else if(strcmp(command, "dec") == 0)
        {
            const char *dec = my_strtok_r(NULL, "/ \t", &saveptr);
            if(strcmp(dec, "chan_mask") == 0)
            {
                line = my_strtok_r(NULL, "", &saveptr);
                line = read_uint(&conf->ChanMask, line, 16);
                if(line && *line != '\0')
                {
                    ERR("Extra junk after mask: %s\n", line);
                    goto fail;
                }
            }
            else if(strcmp(dec, "freq_bands") == 0)
            {
                line = my_strtok_r(NULL, "", &saveptr);
                line = read_uint(&conf->FreqBands, line, 10);
                if(line && *line != '\0')
                {
                    ERR("Extra junk after freq_bands: %s\n", line);
                    goto fail;
                }
                if(conf->FreqBands != 1 && conf->FreqBands != 2)
                {
                    ERR("Invalid freq_bands value: %u\n", conf->FreqBands);
                    goto fail;
                }
            }
            else if(strcmp(dec, "speakers") == 0)
            {
                line = my_strtok_r(NULL, "", &saveptr);
                line = read_uint(&conf->NumSpeakers, line, 10);
                if(line && *line != '\0')
                {
                    ERR("Extra junk after speakers: %s\n", line);
                    goto fail;
                }
                if(conf->NumSpeakers > MAX_OUTPUT_CHANNELS)
                {
                    ERR("Unsupported speaker count: %u\n", conf->NumSpeakers);
                    goto fail;
                }
            }
            else if(strcmp(dec, "coeff_scale") == 0)
            {
                line = my_strtok_r(NULL, " \t", &saveptr);
                if(strcmp(line, "n3d") == 0)
                    conf->CoeffScale = ADS_N3D;
                else if(strcmp(line, "sn3d") == 0)
                    conf->CoeffScale = ADS_SN3D;
                else if(strcmp(line, "fuma") == 0)
                    conf->CoeffScale = ADS_FuMa;
                else
                {
                    ERR("Unsupported coeff scale: %s\n", line);
                    goto fail;
                }
            }
            else
            {
                ERR("Unexpected /dec option: %s\n", dec);
                goto fail;
            }
        }
        else if(strcmp(command, "opt") == 0)
        {
            const char *opt = my_strtok_r(NULL, "/ \t", &saveptr);
            if(strcmp(opt, "xover_freq") == 0)
            {
                line = my_strtok_r(NULL, "", &saveptr);
                line = read_float(&conf->XOverFreq, line);
                if(line && *line != '\0')
                {
                    ERR("Extra junk after xover_freq: %s\n", line);
                    goto fail;
                }
            }
            else if(strcmp(opt, "xover_ratio") == 0)
            {
                line = my_strtok_r(NULL, "", &saveptr);
                line = read_float(&conf->XOverRatio, line);
                if(line && *line != '\0')
                {
                    ERR("Extra junk after xover_ratio: %s\n", line);
                    goto fail;
                }
            }
            else if(strcmp(opt, "input_scale") == 0 || strcmp(opt, "nfeff_comp") == 0 ||
                    strcmp(opt, "delay_comp") == 0 || strcmp(opt, "level_comp") == 0)
            {
                /* Unused */
                my_strtok_r(NULL, " \t", &saveptr);
            }
            else
            {
                ERR("Unexpected /opt option: %s\n", opt);
                goto fail;
            }
        }
        else if(strcmp(command, "speakers") == 0)
        {
            const char *value = my_strtok_r(NULL, "/ \t", &saveptr);
            if(strcmp(value, "{") != 0)
            {
                ERR("Expected { after speakers command, got %s\n", value);
                goto fail;
            }
            if(!load_ambdec_speakers(conf, f, &buffer, &maxlen, &saveptr))
                goto fail;
            value = my_strtok_r(NULL, "/ \t", &saveptr);
            if(!value)
            {
                line = read_clipped_line(f, &buffer, &maxlen);
                if(!line)
                {
                    ERR("Unexpected end of file\n");
                    goto fail;
                }
                value = my_strtok_r(line, "/ \t", &saveptr);
            }
            if(strcmp(value, "}") != 0)
            {
                ERR("Expected } after speaker definitions, got %s\n", value);
                goto fail;
            }
        }
        else if(strcmp(command, "lfmatrix") == 0 || strcmp(command, "hfmatrix") == 0 ||
                strcmp(command, "matrix") == 0)
        {
            const char *value = my_strtok_r(NULL, "/ \t", &saveptr);
            if(strcmp(value, "{") != 0)
            {
                ERR("Expected { after speakers command, got %s\n", value);
                goto fail;
            }
            if(conf->FreqBands == 1)
            {
                if(strcmp(command, "matrix") != 0)
                {
                    ERR("Unexpected \"%s\" type for a single-band decoder\n", command);
                    goto fail;
                }
                if(!load_ambdec_matrix(conf->HFOrderGain, conf->HFMatrix, conf->NumSpeakers,
                                       f, &buffer, &maxlen, &saveptr))
                    goto fail;
            }
            else
            {
                if(strcmp(command, "lfmatrix") == 0)
                {
                    if(!load_ambdec_matrix(conf->LFOrderGain, conf->LFMatrix, conf->NumSpeakers,
                                           f, &buffer, &maxlen, &saveptr))
                        goto fail;
                }
                else if(strcmp(command, "hfmatrix") == 0)
                {
                    if(!load_ambdec_matrix(conf->HFOrderGain, conf->HFMatrix, conf->NumSpeakers,
                                           f, &buffer, &maxlen, &saveptr))
                        goto fail;
                }
                else
                {
                    ERR("Unexpected \"%s\" type for a dual-band decoder\n", command);
                    goto fail;
                }
            }
            value = my_strtok_r(NULL, "/ \t", &saveptr);
            if(!value)
            {
                line = read_clipped_line(f, &buffer, &maxlen);
                if(!line)
                {
                    ERR("Unexpected end of file\n");
                    goto fail;
                }
                value = my_strtok_r(line, "/ \t", &saveptr);
            }
            if(strcmp(value, "}") != 0)
            {
                ERR("Expected } after matrix definitions, got %s\n", value);
                goto fail;
            }
        }
        else if(strcmp(command, "end") == 0)
        {
            line = my_strtok_r(NULL, "/ \t", &saveptr);
            if(line)
            {
                ERR("Unexpected junk on end: %s\n", line);
                goto fail;
            }

            fclose(f);
            free(buffer);
            return 1;
        }
        else
        {
            ERR("Unexpected command: %s\n", command);
            goto fail;
        }

        line = my_strtok_r(NULL, "/ \t", &saveptr);
        if(line)
        {
            ERR("Unexpected junk on line: %s\n", line);
            goto fail;
        }
    }
    ERR("Unexpected end of file\n");

fail:
    fclose(f);
    free(buffer);
    return 0;
}