JOAL學習筆記 第七課 多普勒效應

JOAL學習筆記

 

由於是概念介紹文章,沒有提供實例,這裏給出一個我的測試用例,它是在第一課的基礎上修改的。

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;

import com.jogamp.openal.AL;
import com.jogamp.openal.ALFactory;
import com.jogamp.openal.util.ALut;

public class SingleStaticSource {
	static AL al = ALFactory.getAL();

	// Buffers hold sound data.
	static int[] buffer = new int[1];;

	// Sources are points emitting sound.
	static int[] source = new int[1];

	// Position of the source sound.
	static float[] sourcePos = { 0.0f, -10.0f, 0.0f };//這裏對其速度進行設置,此時相對速度爲10個單位,改變+、-號來控制頻移方向

	// Velocity of the source sound.
	static float[] sourceVel = { 0.0f, 20.0f, 0.0f };//這裏將聲源的位置改變,此時距離聽衆20個單位。

	// Position of the listener.
	static float[] listenerPos = { 0.0f, 0.0f, 0.0f };

	// Velocity of the listener.
	static float[] listenerVel = { 0.0f, 0.0f, 0.0f };

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

	static int loadALData() {

		// variables to load into

		int[] format = new int[1];
		int[] size = new int[1];
		ByteBuffer[] data = new ByteBuffer[1];
		int[] freq = new int[1];
		int[] loop = new int[1];

		// Load wav data into a buffer.
		al.alGenBuffers(1, buffer, 0);
		if (al.alGetError() != AL.AL_NO_ERROR)
			return AL.AL_FALSE;
		
		ALut.alutLoadWAVFile("wavdata/0201_.wav", format, data, size,
				freq, loop);
		al.alBufferData(buffer[0], format[0], data[0], size[0], freq[0]);

		// Bind buffer with a source.
		al.alGenSources(1, source, 0);

		if (al.alGetError() != AL.AL_NO_ERROR)
			return AL.AL_FALSE;

		al.alSourcei(source[0], AL.AL_BUFFER, buffer[0]);
		al.alSourcef(source[0], AL.AL_PITCH, 1.0f);
		al.alSourcef(source[0], AL.AL_GAIN, 1.0f);
		al.alSourcefv(source[0], AL.AL_POSITION, sourcePos, 0);
		al.alSourcefv(source[0], AL.AL_VELOCITY, sourceVel, 0);
		al.alSourcei(source[0], AL.AL_LOOPING, loop[0]);
		// Do another error check and return.
		if (al.alGetError() == AL.AL_NO_ERROR)
			return AL.AL_TRUE;

		return AL.AL_FALSE;
	}

	static void setListenerValues() {
		al.alListenerfv(AL.AL_POSITION, listenerPos, 0);
		al.alListenerfv(AL.AL_VELOCITY, listenerVel, 0);
		al.alListenerfv(AL.AL_ORIENTATION, listenerOri, 0);
	}

	static void killALData() {
		al.alDeleteBuffers(1, buffer, 0);
		al.alDeleteSources(1, source, 0);
		ALut.alutExit();
	}

	public static void main(String[] args) {
		// Initialize OpenAL and clear the error bit.
		ALut.alutInit();
		al.alGetError();
		
		System.out.println(al.alGetInteger(AL.AL_DOPPLER_FACTOR));
		System.out.println(al.alGetInteger(AL.AL_DOPPLER_VELOCITY));
		
		// Load the wav data.
		if (loadALData() == AL.AL_FALSE)
			System.exit(-1);

		setListenerValues();

		// Setup an exit procedure.

		Runtime runtime = Runtime.getRuntime();
		runtime.addShutdownHook(new Thread(new Runnable() {
			public void run() {
				killALData();
			}
		}));
		char[] c = new char[1];
		while (c[0] != 'q') {
			try {
				BufferedReader buf = new BufferedReader(new InputStreamReader(
						System.in));
				System.out
						.println("Press a key and hit ENTER: "
								+ "'p' to play, 's' to stop, 'h' to pause and 'q' to quit");
				buf.read(c);
				switch (c[0]) {
				case 'p':
					// Pressing 'p' will begin playing the sample.
					al.alSourcePlay(source[0]);
					break;
				case 's':
					// Pressing 's' will stop the sample from playing.
					al.alSourceStop(source[0]);
					break;
				case 'h':
					// Pressing 'n' will pause (hold) the sample.
					al.alSourcePause(source[0]);
					break;
				}
			} catch (IOException e) {
				System.exit(1);
			}
		}
	}
}

下面是本次值得注意的地方

 

在第一章開始時,我就對聲源與聽衆速度的設定感到疑惑,即使設定了速度,也需要人爲地加和來改變位置(例如第二課中關於淡出的內容),那麼這個問題在本節中找到了答案,“速度”參數實際上改變的是聲音頻率,而非位置。

 

文末提及的兩個常數參數,“介質速度”與“多普勒係數”,它們的默認值是1.0

 

關於多普勒效應實現的幾個注意點:

1. 聲源與聽衆必須處在不同的位置上,設置的距離不要過大(否則聲音強度過低就無法聽到了,我使用10.0測試還可以)

2. 聲源與聽衆間有相對速度

3. 聲源播放的聲音緩衝區必須屬於單聲道音頻。

在滿足以上條件時,可以聽到明顯的頻率變化。

 

OpenAL中物理量與現實的區別:在現實中,如果質點間存在速度差,則質點間的距離一定在變化之中,文章中提到了不同物理位置受到的多普勒效應影響也不同(而且是非線性的),因此現實中聽衆聽到的頻率一定處於變化之中。OpenAL中,速度影響了頻率但位置依然依賴於外部過程對其位置進行改變(本質上講,與速度無關),所以通過改變速度量可以對應獲得頻率的改變,而對應於特定的速度,頻率在聽衆處是不變的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章