Implement SDL2_mixer and use that for audio

This commit is contained in:
Furkan Mudanyali 2021-12-20 00:52:25 +03:00
parent ca974cc260
commit 090d3fd66c
5 changed files with 97 additions and 81 deletions

View File

@ -1,77 +1,69 @@
package com.fmudanyali;
import javax.sound.sampled.Clip;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.util.LinkedList;
import java.util.Queue;
import org.libsdl.api.rwops.SDL_RWops;
import java.io.File;
import java.io.IOException;
import static org.libsdl.api.rwops.SdlRWops.SDL_RWFromFile;
public class Audio {
private static Queue<String> audioQueue = new LinkedList<String>();
private static Clip clip;
public static void init() throws Exception{
clip = AudioSystem.getClip();
Thread thread = new Thread(){
public void run(){
String current = new String();
while(!Main.exit){
if(audioQueue.isEmpty()){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
if(audioQueue.size() == 1){
clip.loop(Clip.LOOP_CONTINUOUSLY);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
clip.loop(0);
}
if(current != audioQueue.peek()){
current = audioQueue.peek();
try {
addAudio(current);
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
if(clip.getMicrosecondLength() == clip.getMicrosecondPosition() && audioQueue.size() > 1){
audioQueue.remove();
}
}
}
}
};
thread.start();
// Using SDL2_Mixer for native functions
static {
Native.register("SDL2_mixer");
}
public static void playAudio(String file) throws Exception{
File f = new File(FileLoader.getFilePath(file));
AudioInputStream audioIn = AudioSystem.getAudioInputStream(f.toURI().toURL());
clip.open(audioIn);
clip.start();
}
// Constants
public static final int AUDIO_U8 = 0x0008;
public static final int AUDIO_S8 = 0x8008;
public static final int AUDIO_U16LSB = 0x0010;
public static final int AUDIO_S16LSB = 0x8010;
public static final int AUDIO_U16MSB = 0x1010;
public static final int AUDIO_S16MSB = 0x9010;
public static final int AUDIO_U16 = AUDIO_U16LSB;
public static final int AUDIO_S16 = AUDIO_S16LSB;
public static final int AUDIO_S32LSB = 0x8020;
public static final int AUDIO_S32MSB = 0x9020;
public static final int AUDIO_S32 = AUDIO_S32LSB;
public static final int AUDIO_F32LSB = 0x8120;
public static final int AUDIO_F32MSB = 0x9120;
public static final int AUDIO_F32 = AUDIO_F32LSB;
private static void addAudio(String file) throws Exception{
File f = new File(FileLoader.getFilePath(file));
AudioInputStream audioIn = AudioSystem.getAudioInputStream(f.toURI().toURL());
clip.close();
clip.open(audioIn);
}
public static final int MIX_DEFAULT_FREQUENCY = 44100;
public static final int MIX_DEFAULT_FORMAT = AUDIO_S16;
public static final int MIX_DEFAULT_CHANNELS = 2;
public static final int MIX_MAX_VOLUME = 128;
public static final int MIX_CHANNEL_POST = -2;
public static void queueAudio(String file){
audioQueue.add(file);
// Native functions
public static native Pointer Mix_Linked_Version();
public static native int Mix_Init(int flags);
public static native void Mix_Quit();
public static native int Mix_OpenAudio(int frequency, int format, int channels, int chunksize);
public static native void Mix_CloseAudio();
public static native int Mix_QuerySpec(int frequency, int format, int channels);
public static native int Mix_GetNumChunkDecoders();
public static native String Mix_GetChunkDecoder();
public static native Pointer Mix_LoadWAV_RW(SDL_RWops src, int freesrc);
public static native Pointer Mix_LoadMUS(String file);
public static native int Mix_VolumeMusic(int volume);
public static native int Mix_PlayChannelTimed(int channel, Pointer chunk, int loops, int ticks);
public static native int Mix_PlayMusic(Pointer music, int loops);
public static native int Mix_PlayingMusic();
public static native int Mix_PausedMusic();
public static native void Mix_ResumeMusic();
public static native void Mix_PauseMusic();
public static native void Mix_HaltMusic();
public static native void Mix_FreeChunk(Pointer chunk);
public static native void Mix_FreeMusic(Pointer music);
// Defines
public static Pointer Mix_LoadWAV(String file){
return Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1);
}
public static int Mix_PlayChannel(int channel, Pointer chunk, int loops){
return Mix_PlayChannelTimed(channel, chunk, loops, -1);
}
}

View File

@ -31,7 +31,7 @@ public class Main {
}
Render.init();
Screen.init();
Audio.init();
//Audio.init();
scenes.push(new MainMenu());
while(!scenes.empty() && !exit){

View File

@ -17,11 +17,12 @@
package com.fmudanyali.scenes;
import com.fmudanyali.FileLoader;
import com.fmudanyali.Main;
import com.fmudanyali.Screen;
import com.fmudanyali.characters.Player;
import com.fmudanyali.Audio;
import static com.fmudanyali.Audio.*;
import static org.libsdl.api.event.SdlEvents.*;
import static com.fmudanyali.Render.*;
import static org.libsdl.api.keycode.SDL_Keycode.*;
@ -35,8 +36,22 @@ public class Game extends Scene {
public Game() throws Exception{
Screen.makeBackground("scene1/tile.bmp");
Audio.queueAudio("80-search-intro.wav");
Audio.queueAudio("80-search-loop.wav");
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
Mix_VolumeMusic(128);
Thread thread = new Thread(){
public void run(){
try {
Mix_PlayMusic(Mix_LoadMUS(FileLoader.getFilePath("80-search-intro.wav")), 1);
while(Mix_PlayingMusic() == 1);
Mix_PlayMusic(Mix_LoadMUS(FileLoader.getFilePath("80-search-loop.wav")), -1);
Thread.currentThread().interrupt();
return;
} catch(Exception e){
e.printStackTrace();
}
}
};
thread.start();
}
@Override
@ -51,6 +66,7 @@ public class Game extends Scene {
case SDLK_ESCAPE:
if(!escPressed){
Main.scenes.push(new PauseMenu());
Mix_VolumeMusic(30);
escPressed = true;
}
break;

View File

@ -26,6 +26,7 @@ import org.libsdl.api.render.*;
import org.libsdl.api.surface.SDL_Surface;
import static com.fmudanyali.Render.*;
import static com.fmudanyali.Audio.*;
import static org.libsdl.api.render.SdlRender.*;
import static org.libsdl.api.surface.SdlSurface.*;
import static org.libsdl.api.event.SdlEvents.*;
@ -43,6 +44,7 @@ public class MainMenu extends Scene {
private int selection = 0;
public MainMenu() throws Exception{
Mix_PauseMusic();
buttonSize.x = buttonSize.y = 0;
buttonSize.w = startPos.w = exitPos.w = 150;
buttonSize.h = startPos.h = exitPos.h = 100;

View File

@ -20,12 +20,14 @@ package com.fmudanyali.scenes;
import com.fmudanyali.Main;
import com.fmudanyali.Screen;
import com.fmudanyali.FileLoader;
import com.fmudanyali.scenes.MainMenu;
import org.libsdl.api.rect.SDL_Rect;
import org.libsdl.api.render.*;
import org.libsdl.api.surface.SDL_Surface;
import static com.fmudanyali.Render.*;
import static com.fmudanyali.Audio.*;
import static org.libsdl.api.render.SdlRender.*;
import static org.libsdl.api.surface.SdlSurface.*;
import static org.libsdl.api.event.SdlEvents.*;
@ -72,6 +74,7 @@ public class PauseMenu extends Scene {
case SDLK_ESCAPE:
if(!escPressed){
Main.scenes.pop();
Mix_VolumeMusic(128);
escPressed = true;
}
break;
@ -141,15 +144,18 @@ public class PauseMenu extends Scene {
}
}
private void confirm(){
private void confirm() throws Exception{
switch(selection){
case 0:
Main.scenes.pop();
Mix_VolumeMusic(128);
Game.escPressed = false;
break;
case 1:
Main.scenes.pop();
Main.scenes.pop();
Main.scenes.pop();
Main.scenes.push(new MainMenu());
break;
}
}