图像

OpenAL入门和演示集合

最近在开发mac音频相关程序,下面是我整理的一些资源:

OpenAL: Managing Playback Streams

https://developer.tizen.org/development/tutorials/native-application/multimedia/openal

Effectuer des captures audio avec OpenAL

http://loulou.developpez.com/tutoriels/openal/capture/

Play Compressed Formats With OpenAL

http://kcat.strangesoft.net/openal-tutorial.html

OpenAL recording a wav

http://www.gamedev.net/topic/512820-openal-recording-a-wav/

OpenAL Capture

https://www.mario-konrad.ch/wiki/doku.php?id=programming:openal_capture

OpenAL short example

https://ffainelli.github.io/openal-example/

OpenAL Tutorial

http://www.edenwaith.com/products/pige/tutorials/openal.php

最后我来个例子,关于openal录制本地输出设备的声音,并生成aiff格式,当然是apple osx下面:

//
//  main.cpp
//  OpenRecorder
//
//  Created by Jerry Smith on 1/4/16.
//  Copyright © 2016 Jerry Smith. All rights reserved.
//
#include <OpenAL/OpenAL.h>
#include "sndfile.hh"
#include <vector>
#include <iostream>


void saveSound(const std::string& filename, const std::vector<ALshort>& samples)
{
    // set file format
    SF_INFO fileInfos;
    fileInfos.channels   = 2;
    fileInfos.samplerate = 48000;
    fileInfos.format     = SF_FORMAT_PCM_16 | SF_FORMAT_AIFF;
   
    // load file with format
    SNDFILE* file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
    if (!file)
        return;
   
    // write audio
    sf_write_short(file, &samples[0], samples.size());
   
    // close it
    sf_close(file);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    ALCdevice * mainDev;
    mainDev = alcOpenDevice(NULL);
    bool enumeration = alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE");
    if (enumeration == AL_FALSE)
    {
        std::cout<<"can not find output device\n";
    }
    const ALCchar * devices;
    const ALCchar * ptr;
    devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
    ptr = devices;
    //while (ptr[0] != NULL)
    while (*ptr)
    {
        printf("   %s\n", ptr);
        ptr += strlen(ptr) + 1;
    }
   
    ALCcontext * mainContext;

    mainContext = alcCreateContext(mainDev, NULL);
    if (mainContext == NULL)
    {
        alcCloseDevice(mainDev);
        std::cout<<"failed to create context\n";
        return -2;
    }
    if (!alcMakeContextCurrent(mainContext))
    {
        alcDestroyContext(mainContext);
        alcCloseDevice(mainDev);
        std::cout<<"failed to make default context";
        return -3;
    }
    alcProcessContext(mainContext);
   
    const ALCchar *   defaultDeviceName;
    ALCdevice *       defaultDevice;
    bool flag=false;
   
    defaultDevice = alcCaptureOpenDevice(NULL, 48000, AL_FORMAT_MONO16, 4096);
    if (!defaultDevice)
    {
        std::cout<<"with (NULL, 48000, AL_FORMAT_MONO16, 4096)\n";
        defaultDevice = alcCaptureOpenDevice(NULL, 44100, AL_FORMAT_MONO16, 44100);
       
        if(!defaultDevice) {
            std::cout<<"with (NULL, 44100, AL_FORMAT_MONO16, 44100)\n";
            defaultDeviceName=alcGetString(mainDev, ALC_DEVICE_SPECIFIER);
            defaultDevice = alcOpenDevice(defaultDeviceName);
            flag=true;
        }
        if(!defaultDevice) {
            std::cout<<"(mainDev, ALC_DEFAULT_DEVICE_SPECIFIER)\n";
            defaultDeviceName=alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
            defaultDevice = alcOpenDevice(defaultDeviceName);
            flag=true;
        }
        if(!defaultDevice) {
            std::cout<<"(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)\n";
            defaultDevice = alcOpenDevice(NULL);
            bool ext = alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE");
            if (ext == AL_FALSE)
            {
                std::cout<<"with NULL, 'ALC_EXT_CAPTURE'\n";
            }
            flag=true;
        }
       
    }
    std::cout<<"get device: "
             <<alcGetString(defaultDevice, ALC_DEVICE_SPECIFIER)
             <<std::endl;
   
    std::cout<<"start record...\njust 20 seconds for it.\n";
    alcCaptureStart(defaultDevice);
    std::vector<ALshort> outSamples;
    //
    ALCint samplesAvailable;
    ALCint samplesCaptured;
    time_t startTime = time(NULL);
    // int limitBegin = (int)(32767 * 0.9f);
    // int numPlayingSounds=2;
    while (time(NULL) - startTime < 20) {
        // Get the number of samples available
        alcGetIntegerv(defaultDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
       
        // Copy the samples to our capture buffer
        if (samplesAvailable > 0)
        {
            if(samplesAvailable>1024 && flag) {
                samplesAvailable=1024;
            }
            std::size_t startSize = outSamples.size();
            outSamples.resize(startSize + samplesAvailable);
            alcCaptureSamples(defaultDevice, &outSamples[startSize], samplesAvailable);
            samplesCaptured += samplesAvailable;
            printf("Captured %d samples (adding %d)\r", samplesCaptured,
                   samplesAvailable);
            fflush(stdout);
        }
        usleep(10000);
    }
    std::cout<<"stop record...\n";
    alcCaptureStop(defaultDevice);
    // playback
    // Play back the captured data
    printf("Starting playback...\n");
    fflush(stdout);
   
    // Generate an OpenAL buffer for the captured data
    ALuint            buffer;
    ALuint            source;
    ALint             playState;
    alGenBuffers(1, &buffer);
    alGenSources(1, &source);
    alBufferData(buffer, AL_FORMAT_MONO16, &outSamples[0], samplesCaptured*2, 48000);
    alSourcei(source, AL_BUFFER, buffer);
    alSourcePlay(source);
   
    // Wait for the source to stop playing
    playState = AL_PLAYING;
    while (playState == AL_PLAYING)
    {
        printf("  source %d is playing...\r", source);
        fflush(stdout);
        alGetSourcei(source, AL_SOURCE_STATE, &playState);
        usleep(100000);
    }
    printf("\nDone with playback.\n");
    fflush(stdout);
   
    // Shut down OpenAL
    alDeleteSources(1, &source);
    alDeleteBuffers(1, &buffer);
    //
    const std::string filename="output.aiff";
    saveSound(filename, outSamples);
    //
    alDeleteSources(1, &source);
    alDeleteBuffers(1, &buffer);
    //
    alcMakeContextCurrent(NULL);
    alcDestroyContext(mainContext);
    alcCloseDevice(mainDev);
    alcCaptureCloseDevice(defaultDevice);
    //
    return 0;
}

这里面我用到了一个库,libsndfile,大家可以去研究一下。

One thought on “OpenAL入门和演示集合

发表评论