Exemple #1
0
int main(int argc, char *argv[]) {

    if(alcIsExtensionPresent(NULL, "ALC_SOFT_loopback") == ALC_FALSE) {
        fputs("Your OpenAL implementation doesn't support the "
              "\"ALC_SOFT_loopback\" extension, required for this test. "
              "Sorry.\n", stderr);
        exit(EXIT_FAILURE);
    }
    ALCint alc_major, alc_minor;
    alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &alc_major);
    alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &alc_minor);
    if(alc_major<1 || (alc_major==1 && alc_minor<1))
        fputs("Warning : ALC_SOFT_loopback has been written against "
              "the OpenAL 1.1 specification.\n", stderr);

#define HELPER(X) X = alcGetProcAddress(NULL, #X)
    HELPER(alcLoopbackOpenDeviceSOFT);
    HELPER(alcIsRenderFormatSupportedSOFT);
    HELPER(alcRenderSamplesSOFT);
#undef  HELPER
#define HELPER(X) X = alcGetEnumValue(NULL, #X)
    HELPER(ALC_BYTE_SOFT);
    HELPER(ALC_UNSIGNED_BYTE_SOFT);
    HELPER(ALC_SHORT_SOFT);
    HELPER(ALC_UNSIGNED_SHORT_SOFT);
    HELPER(ALC_INT_SOFT);
    HELPER(ALC_UNSIGNED_INT_SOFT);
    HELPER(ALC_FLOAT_SOFT);
    HELPER(ALC_MONO_SOFT);
    HELPER(ALC_STEREO_SOFT);
    HELPER(ALC_QUAD_SOFT);
    HELPER(ALC_5POINT1_SOFT);
    HELPER(ALC_6POINT1_SOFT);
    HELPER(ALC_7POINT1_SOFT);
    HELPER(ALC_FORMAT_CHANNELS_SOFT);
    HELPER(ALC_FORMAT_TYPE_SOFT);
#undef  HELPER

    ALCdevice *loopback_device = alcLoopbackOpenDeviceSOFT(NULL);
    if(!loopback_device) {
        fputs("Could not open loopback device.\n", stderr);
        exit(EXIT_FAILURE);
    }
    if(alcIsRenderFormatSupportedSOFT(loopback_device, 
            22050, ALC_STEREO_SOFT, ALC_SHORT_SOFT) == ALC_FALSE) 
    {
        fputs("The loopback device does not support the "
              "required render format.\n", stderr);
        alcCloseDevice(loopback_device);
        exit(EXIT_FAILURE);
    }

    ALCint attrlist[11] = {
        ALC_MONO_SOURCES, 0,
        ALC_STEREO_SOURCES, 255,
        ALC_FREQUENCY, 22050,
        ALC_FORMAT_CHANNELS_SOFT, ALC_STEREO_SOFT,
        ALC_FORMAT_TYPE_SOFT, ALC_SHORT_SOFT,
        0
    };
    ALCcontext *ctx = alcCreateContext(loopback_device, attrlist);
    alcMakeContextCurrent(ctx);
    alGetError(); /* Clear the error state */

    if(argc<=1) {
        fprintf(stderr, "Usage : %s <small_oggfile>\n", argv[0]);
        alcCloseDevice(loopback_device);
        exit(EXIT_FAILURE);
    }

    SF_INFO sndinfo;
    SNDFILE *snd = sf_open(argv[1], SFM_READ, &sndinfo);
    if(!snd) {
        fprintf(stderr, "Failed to open \"%s\" : %s\n", 
                argv[1], sf_strerror(snd));
        alcCloseDevice(loopback_device);
        exit(EXIT_FAILURE);
    }
    if(sndinfo.channels != 2) {
        fprintf(stderr, "The source sound file has %d channels "
                "(exactly 2 are required).\n", sndinfo.channels);
        alcCloseDevice(loopback_device);
        exit(EXIT_FAILURE);
    }
    short *data = malloc(sndinfo.frames*2*sizeof(short));
    printf("Reading from '%s'...\n", argv[1]);
    sf_readf_short(snd, data, sndinfo.frames);
    sf_close(snd);

    ALuint audio_buffer;
    alGenBuffers(1, &audio_buffer);
    alBufferData(audio_buffer, AL_FORMAT_STEREO16, data,
            sndinfo.frames*2*sizeof(short), sndinfo.samplerate);
    free(data);

    ALuint audio_source;
    alGenSources(1, &audio_source);
    alSourcei(audio_source, AL_BUFFER, audio_buffer);

    unsigned num_frames = sndinfo.frames;
    ALCshort *rendered_samples = malloc(num_frames*2*sizeof(ALCshort));
    sndinfo.samplerate = 22050;
    sndinfo.channels = 2;
    sndinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS | SF_ENDIAN_FILE;
    snd = sf_open("rendered.ogg", SFM_WRITE, &sndinfo);

    alSourcePlay(audio_source);

    puts("Rendering frames...");
    unsigned chunk_size = 4096, off;
    for(off=0 ; off<(num_frames-chunk_size)*2 ; off+=2*chunk_size)
        alcRenderSamplesSOFT(loopback_device, rendered_samples+off, chunk_size);

    puts("Writing to 'rendered.ogg'...");
    sf_write_short(snd, rendered_samples, off-s);
    sf_close(snd);
    free(rendered_samples);

    alDeleteSources(1, &audio_source);
    alDeleteBuffers(1, &audio_buffer);
    alcCloseDevice(loopback_device);
    alcMakeContextCurrent(NULL);
    alcDestroyContext(ctx);

    exit(EXIT_SUCCESS);
}
Exemple #2
0
/**
 * @brief Initializes the output with echo cancelling enabled
 * @return true on success, false otherwise
 * Creates a loopback device and a proxy source on the main output device.
 * If this function returns true only the proxy source should be used for
 * audio output.
 */
bool OpenAL2::initOutputEchoCancel()
{
    // check for the needed extensions for echo cancelation
    if (alcIsExtensionPresent(alOutDev, "ALC_SOFT_loopback") != AL_TRUE) {
        qDebug() << "Device doesn't support loopback";
        return false;
    }
    if (alIsExtensionPresent("AL_SOFT_source_latency") != AL_TRUE) {
        qDebug() << "Device doesn't support source latency";
        return false;
    }

    if (!loadOpenALExtensions(alOutDev)) {
        qDebug() << "Couldn't load needed OpenAL extensions";
        return false;
    }

    // source for proxy output
    alGenSources(1, &alProxySource);
    checkAlError();

    // configuration for the loopback device
    ALCint attrs[] = {ALC_FORMAT_CHANNELS_SOFT,
                      ALC_MONO_SOFT,
                      ALC_FORMAT_TYPE_SOFT,
                      ALC_SHORT_SOFT,
                      ALC_FREQUENCY,
                      Audio::AUDIO_SAMPLE_RATE,
                      0}; // End of List

    alProxyDev = alcLoopbackOpenDeviceSOFT(NULL);
    checkAlcError(alProxyDev);
    if (!alProxyDev) {
        qDebug() << "Couldn't create proxy device";
        alDeleteSources(1, &alProxySource); // cleanup source
        return false;
    }

    if (!alcIsRenderFormatSupportedSOFT(alProxyDev, attrs[5], attrs[1], attrs[3])) {
        qDebug() << "Unsupported format for loopback";
        alcCloseDevice(alProxyDev);         // cleanup loopback dev
        alDeleteSources(1, &alProxySource); // cleanup source
        return false;
    }

    alProxyContext = alcCreateContext(alProxyDev, attrs);
    checkAlcError(alProxyDev);
    if (!alProxyContext) {
        qDebug() << "Couldn't create proxy context";
        alcCloseDevice(alProxyDev);         // cleanup loopback dev
        alDeleteSources(1, &alProxySource); // cleanup source
        return false;
    }

    if (!alcMakeContextCurrent(alProxyContext)) {
        qDebug() << "Cannot activate proxy context";
        alcDestroyContext(alProxyContext);
        alcCloseDevice(alProxyDev);         // cleanup loopback dev
        alDeleteSources(1, &alProxySource); // cleanup source
        return false;
    }

    qDebug() << "Echo cancelation enabled";
    return true;
}