※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

複数の音源を鳴らす-CPP

ALUT CPP Mac OpenAL ソースコード 解説 最終更新日 2009-09-25 : View -
link_pdfプラグインはご利用いただけなくなりました。
ダウンロード View -

OpenALで複数の音源がランダムな位置で鳴るサンプル。
ALUTが必要です。


main.cpp

#include <stdlib.h>
#include <math.h>

#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <AL/alut.h>

#include "keyboard.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()
{
	// Variables to load into.
	ALenum format;
	ALsizei size;
	ALvoid* data;
	ALsizei freq;
	ALboolean loop;

	// Load wav data into buffers.
	alGenBuffers(NUM_BUFFERS, Buffers);

	if(alGetError() != AL_NO_ERROR) return AL_FALSE;
	
	//wavファイルの読み込み(バッファの用意)
	alutLoadWAVFile((ALbyte*)"wavdata/Battle.wav", &format, &data, &size, &freq);
	alBufferData(Buffers[BATTLE], format, data, size, freq);
	alutUnloadWAV(format, data, size, freq);

	alutLoadWAVFile((ALbyte*)"wavdata/Gun1.wav", &format, &data, &size, &freq);
	alBufferData(Buffers[GUN1], format, data, size, freq);
	alutUnloadWAV(format, data, size, freq);

	alutLoadWAVFile((ALbyte*)"wavdata/Gun2.wav", &format, &data, &size, &freq);
	alBufferData(Buffers[GUN2], format, data, size, freq);
	alutUnloadWAV(format, data, size, freq);

	// Bind buffers into audio sources.
	alGenSources(NUM_SOURCES, Sources);

	if(alGetError() != AL_NO_ERROR) return AL_FALSE;
	
	//音源の設定
	alSourcei (Sources[BATTLE], AL_BUFFER,   Buffers[BATTLE]   );
	alSourcef (Sources[BATTLE], AL_PITCH,    1.0f              );
	alSourcef (Sources[BATTLE], AL_GAIN,     1.0f              );
	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.0f            );
	alSourcef (Sources[GUN1], AL_GAIN,     1.0f            );
	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.0f            );
	alSourcef (Sources[GUN2], AL_GAIN,     1.0f            );
	alSourcefv(Sources[GUN2], AL_POSITION, SourcesPos[GUN2]);
	alSourcefv(Sources[GUN2], AL_VELOCITY, SourcesVel[GUN2]);
	alSourcei (Sources[GUN2], AL_LOOPING,  AL_FALSE        );

	// Do another error check and return.
	if(alGetError() != AL_NO_ERROR) return 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);
	alDeleteSources(NUM_SOURCES, Sources);
	alutExit();
}

int main(int argc, char *argv[])
{
    printf("MindCode's OpenAL Lesson 3: Multiple Sources \n\n");
    printf("(Press any key to quit.) \n");

	// Initialize OpenAL and clear the error bit.
	alutInit(NULL, 0);
	alGetError();

	//音源の設定
	if(LoadALData() == AL_FALSE) return 0;
	
	//観測者の設定
	SetListenerValues();

	// Setup an exit procedure.
	//終了時に呼び出す関数
	atexit(KillALData);

	// 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 state;

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

    		if(state != 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]);
            }
		}
	}

	return 0;
}

keyboard.cpp

/*
	This is the unix code for kbhit I found on google at 
	http://www.linuxquestions.org/questions/archive/9/2002/10/4/34027
*/
#include "keyboard.h"

void init_keyboard()
{
	tcgetattr(0,&initial_settings);
	new_settings = initial_settings;
	new_settings.c_lflag &= ~ICANON;
	new_settings.c_lflag &= ~ECHO;
	new_settings.c_lflag &= ~ISIG;
	new_settings.c_cc[VMIN] = 1;
	new_settings.c_cc[VTIME] = 0;
	tcsetattr(0, TCSANOW, &new_settings);
}

void close_keyboard()
{
	tcsetattr(0, TCSANOW, &initial_settings);
}

int kbhit()
{
	char ch;
	int nread;

	if(peek_character != -1)
		return 1;

	new_settings.c_cc[VMIN]=0;
	tcsetattr(0, TCSANOW, &new_settings);
	nread = read(0,&ch,1);
	new_settings.c_cc[VMIN]=1;
	tcsetattr(0, TCSANOW, &new_settings);

	if(nread == 1)
	{
		peek_character = ch;
		return 1;
	}

	return 0;
}

int readch()
{
	char ch;

	if(peek_character != -1)
	{
		ch = peek_character;
		peek_character = -1;
		return ch;
	}
	
	read(0,&ch,1);
	return ch;
}

keyboad.h

/*
        This is the unix code for kbhit I found on google at 
	http://www.linuxquestions.org/questions/archive/9/2002/10/4/34027
*/

#include <stdio.h>
#include <termios.h>
#include <term.h>
#include <curses.h>
#include <unistd.h>

static struct termios initial_settings, new_settings;
static int peek_character = -1;

void init_keyboard();
void close_keyboard();
int kbhit();
int readch();

Makefile

Mac

CC = g++

TARGET = lesson2

COMPILEFLAGS = -framework OpenAL -lalut

$(TARGET): main.o keyboard.o
	$(CC) -o $(TARGET) main.o keyboard.o $(COMPILEFLAGS)

main.o: main.cpp
	$(CC) -c main.cpp -Wno-deprecated

keyboard.o: keyboard.h keyboard.cpp
	$(CC) -c keyboard.cpp -Wno-deprecated

clean:
	rm -f $(TARGET) main.o

実行方法

コンパイルして
make

実行
./lesson3

実行結果


メモ

makeすると以下のようなメッセージが出たりするかもしれません。
main.cpp:66: warning: ‘alutLoadWAVFile’ is deprecated (declared at /usr/local/include/AL/alut.h:110)
これは「alutLoadWAVFile」は今後のバージョンアップで使えなくなるかもよというメッセージです。
ALUTがバージョンアップすると、この関数は別の関数で置き換える必要がでるかも知れないので注意!

テスト環境

MacOSX 10.5.8
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1
OpenAL
ALUT 1.1.0

Tanks



添付ファイル