2015-05-12 92 views
2

好的,這是我的問題。iOS OpenAL聲音不是位置

我正在開發一些幫助類,它爲我封裝了iOS上的OpenAL功能。要知道,它運行得很好,這意味着我可以播放多個聲音(同時)並配置增益和音調。

對我來說,下一步是添加位置聲音。我知道,我必須爲聽衆的位置和來源的位置(和速度,但這不是那麼重要,知道)使用屬性。

問題是,我實現了與互聯網上的教程相對應的所有內容,但聲音總是沒有衰減,所以它不是位置的。

我發現,有時這是由立體聲音頻文件引起的,所以現在我使用單聲道文件,但問題仍然存在。事實上,我從蘋果下載了這個example project。它適用於Mac OS並確實有效。所以我從他們的項目中拿出了聲音文件,然後用我自己的方式使用它們。所以聲音格式應該沒有問題。它仍然不播放位置。

所以我的問題是: 是否可以在iPhone上使用OpenAl播放聲音位置? 如果是的話,應該爲實現3D播放而設置的最低OpenAL屬性是什麼?也許我只是沒有設置一個需要的基本設置。

此外,我認爲模擬器是問題,但是當我在真正的iPhone上測試我的應用程序時,它也不起作用。

我會知道在這裏添加我目前的代碼,但我認爲這太直接找到bug了。我希望有人誰知道我的惱人問題的標準解決方案(其中,我認爲,會有一些小錯誤:d)

所以這裏的代碼:

監聽器:

class Listener { 
    private: 
    vec3 position; 
    vec3 velocity; 
    vec3 at; 
    vec3 up; 
public: 
    Listener(); 

    void setOrientation(vec3 at, vec3 up); 

    vec3 getPosition(); 
    void setPosition(vec3 position); 

    vec3 getVelocity(); 
    void setVelocity(vec3 velocity); 
}; 

Listener::Listener() { 
    alListenerf(AL_GAIN, 0.5f); 
    alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); 
} 

void Listener::setOrientation(vec3 at, vec3 up) 
{ 
    printf("Listener Set Orientation\n"); 
    ALfloat *orientation = (ALfloat*)malloc(6*sizeof(ALfloat)); 
    orientation[0] = at.x; 
    orientation[1] = at.y; 
    orientation[2] = at.z; 
    orientation[3] = up.x; 
    orientation[4] = up.y; 
    orientation[5] = up.z; 
    alListenerfv(AL_ORIENTATION, orientation); 
    this->at = at; 
    this->up = up; 
    free(orientation); 
} 

vec3 Listener::getPosition() 
{ 
    return position; 
} 

void Listener::setPosition(vec3 position) 
{ 
    printf("Listener Set Position\n"); 
    ALfloat *positionArray = (ALfloat*)malloc(3*sizeof(ALfloat)); 
    positionArray[0] = position.x; 
    positionArray[1] = position.y; 
    positionArray[2] = position.z; 
    alListenerfv(AL_POSITION, positionArray); 
    this->position = position; 
    free(positionArray); 
} 

vec3 Listener::getVelocity() 
{ 
    return velocity; 
} 

void Listener::setVelocity(vec3 velocity) 
{ 
    printf("Listener Set Velocity\n"); 
    ALfloat *velArray = (ALfloat*)malloc(3*sizeof(ALfloat)); 
    velArray[0] = velocity.x; 
    velArray[1] = velocity.y; 
    velArray[2] = velocity.z; 
    alListenerfv(AL_VELOCITY, velArray); 
    this->velocity = velocity; 
    free(velArray); 
} 

樣品

class Sample { 
private: 
    UInt32 usageCount;   // Number of Screens using this sound 
    const char *filename;  // The Filename, should be unique! 
    ALuint audioBuffer;  // The sound buffer in which it is stored 
public: 
    Sample(const char* filename); 
    Sample(std::string); 

    void load(); 
    bool unload(); 

    std::string getFilename(); 
    ALuint getAudioBuffer(); 
}; 

Sample::Sample(const char* filename) 
{ 
    usageCount = 0; 
    this->filename = filename; 
} 

Sample::Sample(std::string filename) 
{ 
    usageCount = 0; 
    this->filename = filename.c_str(); 
} 

void Sample::load() 
{ 
    ALenum format; 
    ALvoid* data; 
    ALsizei size; 
    ALsizei freq; 

    if (usageCount == 0) { 
     data = SampleLoader::GetOpenALAudioData(filename, &size, &format, &freq); 

     // Generate Buffer 
     alGenBuffers(1, &audioBuffer); 

     // Fill Buffer With Data 
     alBufferData(audioBuffer, format, data, size, freq); 

     // Free Audio Data 
     if (data) 
     { 
      free(data); 
      data = NULL; 
     } 
    } 

    usageCount++; 
} 

// returns true, if usageCount got zero 
bool Sample::unload() 
{ 
    if (usageCount == 1) { 
     // Delete Buffer 
     alDeleteBuffers(1, &audioBuffer); 
     return true; 
    } 

    usageCount--; 
    return false; 
} 

std::string Sample::getFilename() 
{ 
    std::string strFilename = std::string(filename); 
    return strFilename; 
} 

ALuint Sample::getAudioBuffer() 
{ 
    return audioBuffer; 
} 

來源

class Source { 
    vec3  position; 
    vec3  velocity; 
    vec3  direction; 
    ALfloat  gain; 
    ALfloat  pitch; 
    ALuint  sourceID; 
    Sample  *sample; 
public: 
    void load(); 
    void unload(); 

    ALboolean isPlaying(); 

    void play(); 
    void repeat(); 
    void stop(); 

    void updateSample(Sample *sample); 
    void updatePosition(vec3 position); 
    void updateVelocity(vec3 velocity); 
    void updateDirection(vec3 direcation); 
    void updateOrienation(vec3 position, vec3 velocity, vec3 direction); 
    void updateGain(ALfloat gain); 
    void updatePitch(ALfloat pitch); 
}; 

void Source::load() 
{ 
    alGenSources(1, &sourceID); 

    position = vec3(0.0f, 0.0f, 0.0f); 
    velocity = vec3(0.0f, 0.0f, 0.0f); 
    direction = vec3(0.0f, 0.0f, 0.0f); 

    alSourcefv(sourceID, AL_POSITION, value_ptr(position)); 
    alSourcefv(sourceID, AL_VELOCITY, value_ptr(velocity)); 
    alSourcefv(sourceID, AL_DIRECTION, value_ptr(direction)); 

    gain = 0.5f; 
    pitch = 1.0f; 

    alSourcef(sourceID, AL_GAIN, gain); 
    alSourcef(sourceID, AL_PITCH, pitch); 
} 

void Source::unload() 
{ 
    alDeleteSources(1, &sourceID); 
} 

ALboolean Source::isPlaying() 
{ 
    ALint sourceState; 
    alGetSourcei(sourceID, AL_SOURCE_STATE, &sourceState); 
    return (sourceState == AL_PLAYING); 
} 

void Source::play() 
{ 
    alSourcei(sourceID, AL_LOOPING, AL_FALSE); 
    alSourcePlay(sourceID); 
} 

void Source::repeat() 
{ 
    alSourcei(sourceID, AL_LOOPING, AL_TRUE); 
    alSourcePlay(sourceID); 
} 

void Source::stop() 
{ 
    alSourceStop(sourceID); 
} 

void Source::updateSample(Sample *sample) 
{ 
    alSourcei(sourceID, AL_BUFFER, sample->getAudioBuffer()); 
} 

void Source::updatePosition(vec3 position) 
{ 
    alSource3f(sourceID, AL_POSITION, position.x, position.y, position.z); 
} 

void Source::updateVelocity(vec3 velocity) 
{ 
    alSourcefv(sourceID, AL_VELOCITY, value_ptr(velocity)); 
} 

void Source::updateDirection(vec3 direction) 
{ 
    alSourcefv(sourceID, AL_DIRECTION, value_ptr(direction)); 
} 

void Source::updateOrienation(vec3 position, vec3 velocity, vec3 direction) 
{ 
    alSourcefv(sourceID, AL_POSITION, value_ptr(position)); 
    alSourcefv(sourceID, AL_VELOCITY, value_ptr(velocity)); 
    alSourcefv(sourceID, AL_DIRECTION, value_ptr(direction)); 
} 

void Source::updateGain(ALfloat gain) 
{ 
    alSourcef(sourceID, AL_GAIN, gain); 
} 

void Source::updatePitch(ALfloat pitch) 
{ 
    alSourcef(sourceID, AL_PITCH, pitch); 
} 

樣品加載函數,從項目從蘋果採取

void* SampleLoader::GetOpenALAudioData(const char* filename, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate) 
{ 
    OSStatus      err = noErr; 
    SInt64       theFileLengthInFrames = 0; 
    AudioStreamBasicDescription  theFileFormat; 
    UInt32       thePropertySize = sizeof(theFileFormat); 
    ExtAudioFileRef     extRef = NULL; 
    void*       theData = NULL; 
    AudioStreamBasicDescription  theOutputFormat; 

    // Create Path 
    NSString *filenameString = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding]; 
    NSArray *components = [filenameString componentsSeparatedByString:@"."]; 

    NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:[components objectAtIndex:0] ofType:[components objectAtIndex:1]]; 
    NSURL *audioFileURL = [NSURL fileURLWithPath:audioFilePath]; 
    CFURLRef inFileURL = (__bridge CFURLRef)audioFileURL; 

    // Open a file with ExtAudioFileOpen() 
    err = ExtAudioFileOpenURL(inFileURL, &extRef); 
    if(err) { 
     printf("MyGetOpenALAudioData: ExtAudioFileOpenURL FAILED, Error = %d\n", (int)err); 

     // Dispose the ExtAudioFileRef, it is no longer needed 
     if (extRef) ExtAudioFileDispose(extRef); 
     return theData; 
    } 

    // Get the audio data format 
    err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat); 
    if(err) { 
     printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %d\n", (int)err); 

     // Dispose the ExtAudioFileRef, it is no longer needed 
     if (extRef) ExtAudioFileDispose(extRef); 
     return theData; 
    } 
    if (theFileFormat.mChannelsPerFrame > 2) { 
     printf("MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); 

     // Dispose the ExtAudioFileRef, it is no longer needed 
     if (extRef) ExtAudioFileDispose(extRef); 
     return theData; 
    } 

    // Set the client format to 16 bit signed integer (native-endian) data 
    // Maintain the channel count and sample rate of the original source format 
    theOutputFormat.mSampleRate = theFileFormat.mSampleRate; 
    theOutputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame; 

    theOutputFormat.mFormatID = kAudioFormatLinearPCM; 
    theOutputFormat.mBytesPerPacket = 2 * theOutputFormat.mChannelsPerFrame; 
    theOutputFormat.mFramesPerPacket = 1; 
    theOutputFormat.mBytesPerFrame = 2 * theOutputFormat.mChannelsPerFrame; 
    theOutputFormat.mBitsPerChannel = 16; 
    theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; 

    // Set the desired client (output) data format 
    err = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(theOutputFormat), &theOutputFormat); 
    if(err) { 
     printf("MyGetOpenALAudioData: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) FAILED, Error = %d\n", (int)err); 

     // Dispose the ExtAudioFileRef, it is no longer needed 
     if (extRef) ExtAudioFileDispose(extRef); 
     return theData; 
    } 

    // Get the total frame count 
    thePropertySize = sizeof(theFileLengthInFrames); 
    err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames); 
    if(err) { 
     printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %d\n", (int)err); 

     // Dispose the ExtAudioFileRef, it is no longer needed 
     if (extRef) ExtAudioFileDispose(extRef); 
     return theData; 
    } 

    // Read all the data into memory 
    UInt32 theFramesToRead = (UInt32)theFileLengthInFrames; 
    UInt32 dataSize = theFramesToRead * theOutputFormat.mBytesPerFrame;; 
    theData = malloc(dataSize); 
    if (theData) 
    { 
     AudioBufferList  theDataBuffer; 
     theDataBuffer.mNumberBuffers = 1; 
     theDataBuffer.mBuffers[0].mDataByteSize = dataSize; 
     theDataBuffer.mBuffers[0].mNumberChannels = theOutputFormat.mChannelsPerFrame; 
     theDataBuffer.mBuffers[0].mData = theData; 

     // Read the data into an AudioBufferList 
     err = ExtAudioFileRead(extRef, &theFramesToRead, &theDataBuffer); 
     if(err == noErr) 
     { 
      // success 
      *outDataSize = (ALsizei)dataSize; 
      *outDataFormat = (theOutputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; 
      *outSampleRate = (ALsizei)theOutputFormat.mSampleRate; 
     } 
     else 
     { 
      // failure 
      free (theData); 
      theData = NULL; // make sure to return NULL 
      printf("MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %d\n", (int)err); 

      // Dispose the ExtAudioFileRef, it is no longer needed 
      if (extRef) ExtAudioFileDispose(extRef); 
      return theData; 
     }  
    } 

    // Dispose the ExtAudioFileRef, it is no longer needed 
    if (extRef) ExtAudioFileDispose(extRef); 
    return theData; 
} 

SoundManager類

namespace SoundManager { 
    extern ALCdevice *openALDevice; 
    extern ALCcontext *openALContext; 

    extern std::vector<Sample*> samples; 

    void initialize(); 
    void release(); 

    Sample* manage(const char* filename); 
    Sample* manage(std::string filename); 
    void remove(Sample *sample); 
} 

namespace SoundManager { 
    ALCdevice *openALDevice; 
    ALCcontext *openALContext; 

    std::vector<Sample*> samples; 
} 

void AudioInterruptionListenerCallback(void* user_data, UInt32 interruption_state) 
{ 
    if (kAudioSessionBeginInterruption == interruption_state) 
    { 
     alcMakeContextCurrent(NULL); 
    } 
    else if (kAudioSessionEndInterruption == interruption_state) 
    { 
     AudioSessionSetActive(true); 
     alcMakeContextCurrent(SoundManager::openALContext); 
    } 
} 

void SoundManager::initialize() 
{ 
    AudioSessionInitialize(NULL, NULL, AudioInterruptionListenerCallback, NULL); 

    UInt32 session_category = kAudioSessionCategory_MediaPlayback; 
    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(session_category), &session_category); 

    AudioSessionSetActive(true); 

    // Open Device 
    openALDevice = alcOpenDevice(NULL); 

    // Create and activate context 
    openALContext = alcCreateContext(openALDevice, NULL); 
    alcMakeContextCurrent(openALContext); 
} 

void SoundManager::release() 
{ 
    // Give up Context and destroy it 
    alcMakeContextCurrent(NULL); 
    alcDestroyContext(openALContext); 

    // Close device 
    alcCloseDevice(openALDevice); 
} 

Sample* SoundManager::manage(const char* filename) 
{ 
    return manage(std::string(filename)); 
} 

Sample* SoundManager::manage(std::string filename) 
{ 
    if (samples.size() >= kMaxNumberOfSamples) { 
     Engine::warning("Max number of samples reached! Release one first"); 
     return NULL; 
    } 

    // If Sound is already managed, load the managed again 
    for (int i=0; i<samples.size(); i++) { 
     if (samples[i]->getFilename().compare(filename) == 0) { 
      printf("Already loaded\n"); 
      samples[i]->load(); 
      return samples[i]; 
     } 
    } 

    // Otherwise load the new sound and manage it 
    printf("Load new sound\n"); 
    Sample *sample = new Sample(filename); 
    sample->load(); 
    samples.push_back(sample); 
    return sample; 
} 

void SoundManager::remove(Sample *sample) 
{ 
    for (int i=0; i<samples.size(); i++) { 
     if (samples[i]->getFilename().compare(sample->getFilename()) == 0) { 
      // If Sound isn't in use from anywhere else, unmanage it 
      if (samples[i]->unload()) { 
       samples.erase(std::remove(samples.begin(), samples.end(), sample), samples.end()); 
       return; 
      } 
     } 
    } 

    Engine::warning("The sound to be removed wasn't managed!"); 
} 

所以就在這裏,這是爲源,緩衝器和監聽器和一個管理者,所有的包裝類,其只是確保樣品只加載一次。所有這些都應用在屏幕類中,並在我的簡單引擎中呈現。它是獨立的,應該播放從左到右移動的聲音。但它不:

class SoundTestScreen : public Screen 
{ 
private: 
    void initialize(); 
    void load(); 
    void unload(); 

    void update(Time &time); 
    void draw(Time &time); 

private: 
    Listener listener; 
    Sample *bubbles; 
    Source *bubbleSource; 

    double totalTime; 
    double lastPlayTime; 
}; 

void SoundTestScreen::initialize() 
{  
    listener.setPosition(vec3(0, 0, 0)); 
    listener.setVelocity(vec3(0, 0, 0)); 
    listener.setOrientation(vec3(0, 0, -1),vec3(0, 1, 0)); 

    totalTime = 0; 
    lastPlayTime = 0; 

    // Create Sources to play the samples 
    bubbleSource = new Source(); 
} 

void SoundTestScreen::load() 
{ 
    // Only load sample once 
    bubbles = SoundManager::manage("sound_electric.wav"); 

    bubbleSource->load(); 
    bubbleSource->updateSample(bubbles); 
    bubbleSource->updatePosition(vec3(0,0,0)); 
    bubbleSource->repeat(); 
} 

void SoundTestScreen::unload() 
{ 
    // Only unload sample once 
    SoundManager::remove(bubbles); 

    bubbleSource->unload(); 
} 

void SoundTestScreen::update(Time &time) 
{ 
    bubbleSource->updatePosition(vec3(100*sinf(time.ElapsedTime),0,0)); 
} 

void SoundTestScreen::draw(Time &time) 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
} 

這一切都只是一些基本的實現,但我真的不知道爲什麼聲音不位置。

我真的很希望有人能找到我的錯誤,這很煩人。

問候


編輯:

它的工作現在,只有一些小的錯誤,我現在糾正,但沒有找到很長一段時間。 我將這個代碼留給那些正在尋找一些iOS上的聲音系統的人來使用,這些聲音系統在互聯網上很少見。

回答

0

哇,當您給出示例代碼時,您會打倒雷霆! :d

讓我學到,這是位置代碼是這樣的:

#include <conio.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <time.h> 
#include <AL\al.h> 
#include <AL\alc.h> 
#include <AL\alut.h> 

// Maximum data buffers we will need. 
#define NUM_BUFFERS 3 

// Maximum emissions we will need. 
#define NUM_SOURCES 3 

// These index the buffers and sources. 
#define BATTLE  0 
#define GUN1  1 
#define GUN2  2 

// Buffers hold sound data. 
ALuint Buffers[NUM_BUFFERS]; 

// Sources are points of emitting sound. 
ALuint Sources[NUM_SOURCES]; 

// Position of the source sounds. 
ALfloat SourcesPos[NUM_SOURCES][3]; 

// Velocity of the source sounds. 
ALfloat SourcesVel[NUM_SOURCES][3]; 


// Position of the listener. 
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 }; 

// Velocity of the listener. 
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 }; 

// Orientation of the listener. (first 3 elements are "at", second 3 are "up") 
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 }; 


/* 
* ALboolean LoadALData() 
* 
* This function will load our sample data from the disk using the Alut 
* utility and send the data into OpenAL as a buffer. A source is then 
* also created to play that buffer. 
*/ 
ALboolean LoadALData() 
{ 

    alutInit (NULL, NULL); 

    //ALUT allows us to point to a buffer object using an ALuint. 
    // furthermore, there are calls that allow you to load from memory. 
    Buffers[BATTLE] = alutCreateBufferFromFile("C:\\Users\\Lee\\Desktop\\OpenAL\\OpenALStaticSound\\wavdata\\Battle.wav"); 
    Buffers[GUN1] = alutCreateBufferFromFile("C:\\Users\\Lee\\Desktop\\OpenAL\\OpenALStaticSound\\wavdata\\Gun1.wav"); 
    Buffers[GUN2] = alutCreateBufferFromFile("C:\\Users\\Lee\\Desktop\\OpenAL\\OpenALStaticSound\\wavdata\\Gun2.wav"); 

    // Bind the buffer with the source. 
    //alGenSources (1, &Source); 
    alGenSources(NUM_SOURCES, Sources); 

    //Attach any special modifications to the source 
    //alSourcei (Source, AL_BUFFER, Buffer ); 
    //alSourcef (Source, AL_PITCH, 1.0  ); 
    //alSourcef (Source, AL_GAIN,  1.0  ); 
    //alSourcefv(Source, AL_POSITION, SourcePos); 
    //alSourcefv(Source, AL_VELOCITY, SourceVel); 
    //alSourcei (Source, AL_LOOPING, AL_TRUE ); 

    alSourcei (Sources[BATTLE], AL_BUFFER, Buffers[BATTLE] ); 
    alSourcef (Sources[BATTLE], AL_PITCH, 1.0    ); 
    alSourcef (Sources[BATTLE], AL_GAIN,  1.0    ); 
    alSourcefv(Sources[BATTLE], AL_POSITION, SourcesPos[BATTLE]); 
    alSourcefv(Sources[BATTLE], AL_VELOCITY, SourcesVel[BATTLE]); 
    alSourcei (Sources[BATTLE], AL_LOOPING, AL_TRUE   ); 

    alSourcei (Sources[GUN1], AL_BUFFER, Buffers[GUN1] ); 
    alSourcef (Sources[GUN1], AL_PITCH, 1.0   ); 
    alSourcef (Sources[GUN1], AL_GAIN,  1.0   ); 
    alSourcefv(Sources[GUN1], AL_POSITION, SourcesPos[GUN1]); 
    alSourcefv(Sources[GUN1], AL_VELOCITY, SourcesVel[GUN1]); 
    alSourcei (Sources[GUN1], AL_LOOPING, AL_FALSE  ); 

    alSourcei (Sources[GUN2], AL_BUFFER, Buffers[GUN2] ); 
    alSourcef (Sources[GUN2], AL_PITCH, 1.0   ); 
    alSourcef (Sources[GUN2], AL_GAIN,  1.0   ); 
    alSourcefv(Sources[GUN2], AL_POSITION, SourcesPos[GUN2]); 
    alSourcefv(Sources[GUN2], AL_VELOCITY, SourcesVel[GUN2]); 
    alSourcei (Sources[GUN2], AL_LOOPING, AL_FALSE  ); 



    return AL_TRUE; 
} 

/* 
* void SetListenerValues() 
* 
* We already defined certain values for the Listener, but we need 
* to tell OpenAL to use that data. This function does just that. 
*/ 
void SetListenerValues() 
{ 
    alListenerfv(AL_POSITION, ListenerPos); 
    alListenerfv(AL_VELOCITY, ListenerVel); 
    alListenerfv(AL_ORIENTATION, ListenerOri); 
} 

/* 
* void KillALData() 
* 
* We have allocated memory for our buffers and sources which needs 
* to be returned to the system. This function frees that memory. 
*/ 
void KillALData() 
{ 
    alDeleteBuffers(NUM_BUFFERS, &Buffers[0]); 
    alDeleteSources(NUM_SOURCES, &Sources[0]); 
    alutExit(); 
} 


int main(){ 


    printf("Original Tutorial : MindCode's OpenAL Lesson 1: Single Static Source\n\n"); 
    printf("Updated Tutorial : Lesley A. Gushurst\n"); 

    alutInit(NULL, 0); 
    //alGetError(); 

    // Load the wav data. 

    if(LoadALData() == AL_FALSE) 
    { 
     printf("Error loading data."); 
     return 0; 
    } else { 
     // Begin the battle sample to play. 
     alSourcePlay(Sources[BATTLE]); 

     // Go through all the sources and check that they are playing. 
     // Skip the first source because it is looping anyway (will always be playing). 
     ALint play; 

     while (!_kbhit()) 
     { 
      for (int i = 1; i < NUM_SOURCES; i++) 
      { 
        alGetSourcei(Sources[i], AL_SOURCE_STATE, &play); 

        if (play != AL_PLAYING) 
        { 
         // Pick a random position around the listener to play the source. 

         double theta = (double) (rand() % 360) * 3.14/180.0; 

         SourcesPos[i][0] = -float(cos(theta)); 
         SourcesPos[i][1] = -float(rand()%2); 
         SourcesPos[i][2] = -float(sin(theta)); 

         alSourcefv(Sources[i], AL_POSITION, SourcesPos[i]); 

         alSourcePlay(Sources[i]); 
        } 
      } 
     } 
     getchar(); 
    } 

    return 0; 
} 

我想嘗試這個代碼,如果它的工作原理,那麼也許你的問題「是否可以播放聲音位置在iPhone上使用OpenAl?「將得到回答。我不確定,因爲我沒有做過移動開發,但我認爲這將是一個很好的起點。非常尊重MindCode。你必須用別的東西替換wav文件來測試它(而不是像我那樣硬編碼)。

+1

謝謝你!即使根據您的示例重新編寫我的代碼後,iOS上不支持alut,我也會喜歡我的錯誤。它真的很笨,必須交換一個變量:D在Sample :: load()中,AL_FORMAT_STEREO16必須替換爲從前一個函數計算出來的'format'。這就是爲什麼它不是位置! – acloD128

+0

哎呀!完全忘了ALUT和iOS。 –

+0

謝謝:) – acloD128