mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-11 13:31:07 -04:00
Add music loading/playing using portaudio and stb_vorbis.
This commit is contained in:
parent
4d092126cc
commit
4fcfd10307
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "mach-freetype"]
|
[submodule "mach-freetype"]
|
||||||
path = mach-freetype
|
path = mach-freetype
|
||||||
url = https://github.com/hexops/mach-freetype
|
url = https://github.com/hexops/mach-freetype
|
||||||
|
[submodule "portaudio"]
|
||||||
|
path = portaudio
|
||||||
|
url = git@github.com:PortAudio/portaudio.git
|
||||||
|
34
assets/cubyz/biomes/colorado_mountains.json
Normal file
34
assets/cubyz/biomes/colorado_mountains.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"type" : "mountain_grassland",
|
||||||
|
"minHeight" : 60,
|
||||||
|
"maxHeight" : 256,
|
||||||
|
|
||||||
|
"roughness" : 10,
|
||||||
|
"mountains" : 20,
|
||||||
|
"hills" : 50,
|
||||||
|
|
||||||
|
"rivers" : true,
|
||||||
|
|
||||||
|
"ground_structure" : [
|
||||||
|
],
|
||||||
|
"stoneBlock" : "cubyz:colorado_stone",
|
||||||
|
"structures" : [
|
||||||
|
{
|
||||||
|
"id" : "cubyz:simple_tree",
|
||||||
|
"leaves" : "cubyz:colorado_stone",
|
||||||
|
"log" : "cubyz:colorado_stone",
|
||||||
|
"top" : "cubyz:colorado_stone",
|
||||||
|
"chance" : 0.001,
|
||||||
|
"type" : "round",
|
||||||
|
"height" : 3,
|
||||||
|
"height_variation" : 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id" : "cubyz:boulder",
|
||||||
|
"chance" : 0.001,
|
||||||
|
"block" : "cubyz:colorado_stone",
|
||||||
|
"size" : 2,
|
||||||
|
"size_variance" : 7
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
assets/cubyz/blocks/colorado_stone.json
Normal file
10
assets/cubyz/blocks/colorado_stone.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"class" : "stone",
|
||||||
|
"hardness" : 20,
|
||||||
|
"breakingPower" : 1,
|
||||||
|
"drops" : [
|
||||||
|
"auto"
|
||||||
|
],
|
||||||
|
"model" : "cube",
|
||||||
|
"texture" : "cubyz:colorado_stone"
|
||||||
|
}
|
BIN
assets/cubyz/blocks/textures/colorado_stone.png
Normal file
BIN
assets/cubyz/blocks/textures/colorado_stone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 861 B |
BIN
assets/cubyz/music/DarkTimes.ogg
Normal file
BIN
assets/cubyz/music/DarkTimes.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/EasternThought.ogg
Normal file
BIN
assets/cubyz/music/EasternThought.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/GymnopedieNo1.ogg
Normal file
BIN
assets/cubyz/music/GymnopedieNo1.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/KingBoard.ogg
Normal file
BIN
assets/cubyz/music/KingBoard.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/Sincerely.ogg
Normal file
BIN
assets/cubyz/music/Sincerely.ogg
Normal file
Binary file not shown.
37
assets/cubyz/music/credits.txt
Normal file
37
assets/cubyz/music/credits.txt
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
TotalDemented ( https://www.youtube.com/channel/UCut9PCEq4cEJogfEPUXk7Gg ):
|
||||||
|
cubyz.ogg
|
||||||
|
leaves.ogg
|
||||||
|
in_the_depths.ogg
|
||||||
|
|
||||||
|
|
||||||
|
sinanimea:
|
||||||
|
sunrise.ogg
|
||||||
|
under_the_water_sky.ogg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Kevin MacLeod
|
||||||
|
|
||||||
|
Syncerely by Kevin MacLeod
|
||||||
|
Link: https://incompetech.filmmusic.io/song/5033-sincerely
|
||||||
|
License: https://filmmusic.io/standard-license
|
||||||
|
|
||||||
|
Gymnopedie No. 1 by Kevin MacLeod
|
||||||
|
Link: https://incompetech.filmmusic.io/song/3837-gymnopedie-no-1
|
||||||
|
License: https://filmmusic.io/standard-license
|
||||||
|
|
||||||
|
Dark Times by Kevin MacLeod
|
||||||
|
Link: https://incompetech.filmmusic.io/song/3611-dark-times
|
||||||
|
License: https://filmmusic.io/standard-license
|
||||||
|
|
||||||
|
Eastern Thought by Kevin MacLeod
|
||||||
|
Link: https://incompetech.filmmusic.io/song/3692-eastern-thought
|
||||||
|
License: https://filmmusic.io/standard-license
|
||||||
|
|
||||||
|
Mana Two Part 2 by Kevin MacLeod
|
||||||
|
Link: https://incompetech.filmmusic.io/song/5713-mana-two-part-2
|
||||||
|
License: https://filmmusic.io/standard-license
|
||||||
|
|
||||||
|
Heart of the Beast by Kevin MacLeod
|
||||||
|
Link: https://incompetech.filmmusic.io/song/3862-heart-of-the-beast
|
||||||
|
License: https://filmmusic.io/standard-license
|
BIN
assets/cubyz/music/cubyz.ogg
Normal file
BIN
assets/cubyz/music/cubyz.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/heart-of-the-beast.ogg
Normal file
BIN
assets/cubyz/music/heart-of-the-beast.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/in_the_depths.ogg
Normal file
BIN
assets/cubyz/music/in_the_depths.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/leaves.ogg
Normal file
BIN
assets/cubyz/music/leaves.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/mana-two-part-2.ogg
Normal file
BIN
assets/cubyz/music/mana-two-part-2.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/sunrise.ogg
Normal file
BIN
assets/cubyz/music/sunrise.ogg
Normal file
Binary file not shown.
BIN
assets/cubyz/music/under_the_water_sky.ogg
Normal file
BIN
assets/cubyz/music/under_the_water_sky.ogg
Normal file
Binary file not shown.
30
build.zig
30
build.zig
@ -43,7 +43,35 @@ pub fn build(b: *std.build.Builder) !void {
|
|||||||
std.log.err("Unsupported target: {}\n", .{ target.getOsTag() });
|
std.log.err("Unsupported target: {}\n", .{ target.getOsTag() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exe.addCSourceFiles(&[_][]const u8{"lib/glad.c", "lib/stb_image.c", "lib/stb_image_write.c"}, &[_][]const u8{"-g", "-O3"});
|
{ // compile portaudio from source:
|
||||||
|
exe.addIncludePath("portaudio/include");
|
||||||
|
exe.addIncludePath("portaudio/src/common");
|
||||||
|
exe.addCSourceFiles(&[_][]const u8 {
|
||||||
|
"portaudio/src/common/pa_allocation.c",
|
||||||
|
"portaudio/src/common/pa_converters.c",
|
||||||
|
"portaudio/src/common/pa_cpuload.c",
|
||||||
|
"portaudio/src/common/pa_debugprint.c",
|
||||||
|
"portaudio/src/common/pa_dither.c",
|
||||||
|
"portaudio/src/common/pa_front.c",
|
||||||
|
"portaudio/src/common/pa_process.c",
|
||||||
|
"portaudio/src/common/pa_ringbuffer.c",
|
||||||
|
"portaudio/src/common/pa_stream.c",
|
||||||
|
"portaudio/src/common/pa_trace.c",
|
||||||
|
}, &[_][]const u8{"-g", "-O3"});
|
||||||
|
if(target.getOsTag() == .windows) {
|
||||||
|
// TODO: Choose a host API
|
||||||
|
} else if(target.getOsTag() == .linux) {
|
||||||
|
// unix:
|
||||||
|
exe.addCSourceFiles(&[_][]const u8 {"portaudio/src/os/unix/pa_unix_hostapis.c", "portaudio/src/os/unix/pa_unix_util.c"}, &[_][]const u8{"-g", "-O3", "-DPA_USE_ALSA"});
|
||||||
|
exe.addIncludePath("portaudio/src/os/unix");
|
||||||
|
// ALSA:
|
||||||
|
exe.addCSourceFiles(&[_][]const u8 {"portaudio/src/hostapi/alsa/pa_linux_alsa.c"}, &[_][]const u8{"-g", "-O3"});
|
||||||
|
exe.linkSystemLibrary("alsa");
|
||||||
|
} else {
|
||||||
|
std.log.err("Unsupported target: {}\n", .{ target.getOsTag() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exe.addCSourceFiles(&[_][]const u8{"lib/glad.c", "lib/stb_image.c", "lib/stb_image_write.c", "lib/stb_vorbis.c"}, &[_][]const u8{"-g", "-O3"});
|
||||||
exe.addAnonymousModule("gui", .{.source_file = .{.path = "src/gui/gui.zig"}});
|
exe.addAnonymousModule("gui", .{.source_file = .{.path = "src/gui/gui.zig"}});
|
||||||
exe.addAnonymousModule("server", .{.source_file = .{.path = "src/server/server.zig"}});
|
exe.addAnonymousModule("server", .{.source_file = .{.path = "src/server/server.zig"}});
|
||||||
const harfbuzzModule = freetype.harfbuzzModule(b);
|
const harfbuzzModule = freetype.harfbuzzModule(b);
|
||||||
|
5584
include/stb/stb_vorbis.h
Normal file
5584
include/stb/stb_vorbis.h
Normal file
File diff suppressed because it is too large
Load Diff
3
lib/stb_vorbis.c
Normal file
3
lib/stb_vorbis.c
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#define STB_VORBIS_NO_PUSHDATA_API
|
||||||
|
#define STB_VORBIS_NO_INTEGER_CONVERSION
|
||||||
|
#include "stb/stb_vorbis.h"
|
1
portaudio
Submodule
1
portaudio
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit cb8d3dcbc6fa74c67f3e236be89b12d5630da141
|
91
src/audio.zig
Normal file
91
src/audio.zig
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const main = @import("root");
|
||||||
|
|
||||||
|
const c = @cImport ({
|
||||||
|
@cInclude("portaudio.h");
|
||||||
|
@cDefine("STB_VORBIS_HEADER_ONLY", "");
|
||||||
|
@cInclude("stb/stb_vorbis.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
fn handleError(paError: c_int) void {
|
||||||
|
if(paError != c.paNoError) {
|
||||||
|
std.log.err("PortAudio error: {s}", .{c.Pa_GetErrorText(paError)});
|
||||||
|
@panic("Audio error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Proper sound and music system
|
||||||
|
// TODO: volume control
|
||||||
|
|
||||||
|
var stream: ?*c.PaStream = null;
|
||||||
|
|
||||||
|
var musicData: []f32 = undefined; // TODO: Add a caching system for music data.
|
||||||
|
|
||||||
|
const sampleRate = 44100;
|
||||||
|
|
||||||
|
pub fn init() !void {
|
||||||
|
handleError(c.Pa_Initialize());
|
||||||
|
|
||||||
|
handleError(c.Pa_OpenDefaultStream(
|
||||||
|
&stream,
|
||||||
|
0, // input channels
|
||||||
|
2, // stereo output
|
||||||
|
c.paFloat32,
|
||||||
|
sampleRate, // TODO: There must be some target dependant value to put here.
|
||||||
|
c.paFramesPerBufferUnspecified,
|
||||||
|
&patestCallback,
|
||||||
|
null
|
||||||
|
));
|
||||||
|
|
||||||
|
var err: c_int = 0;
|
||||||
|
const ogg_stream = c.stb_vorbis_open_filename("assets/cubyz/music/cubyz.ogg", &err, null);
|
||||||
|
defer c.stb_vorbis_close(ogg_stream);
|
||||||
|
if(ogg_stream != null) {
|
||||||
|
const ogg_info: c.stb_vorbis_info = c.stb_vorbis_get_info(ogg_stream);
|
||||||
|
std.debug.assert(sampleRate == ogg_info.sample_rate); // TODO: Handle this case
|
||||||
|
std.debug.assert(2 == ogg_info.channels); // TODO: Handle this case
|
||||||
|
const samples = c.stb_vorbis_stream_length_in_samples(ogg_stream);
|
||||||
|
musicData = try main.globalAllocator.alloc(f32, samples*@intCast(usize, ogg_info.channels));
|
||||||
|
_ = c.stb_vorbis_get_samples_float_interleaved(ogg_stream, ogg_info.channels, musicData.ptr, @intCast(c_int, samples)*ogg_info.channels);
|
||||||
|
} else {
|
||||||
|
std.log.err("Error reading file TODO", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(c.Pa_StartStream(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit() void {
|
||||||
|
handleError(c.Pa_StopStream(stream));
|
||||||
|
handleError(c.Pa_CloseStream(stream));
|
||||||
|
handleError(c.Pa_Terminate());
|
||||||
|
main.globalAllocator.free(musicData);
|
||||||
|
}
|
||||||
|
|
||||||
|
var curIndex: usize = 0;
|
||||||
|
|
||||||
|
fn patestCallback(
|
||||||
|
inputBuffer: ?*const anyopaque,
|
||||||
|
outputBuffer: ?*anyopaque,
|
||||||
|
framesPerBuffer: c_ulong,
|
||||||
|
timeInfo: ?*const c.PaStreamCallbackTimeInfo,
|
||||||
|
statusFlags: c.PaStreamCallbackFlags,
|
||||||
|
userData: ?*anyopaque
|
||||||
|
) callconv(.C) c_int {
|
||||||
|
// This routine will be called by the PortAudio engine when audio is needed.
|
||||||
|
// It may called at interrupt level on some machines so don't do anything
|
||||||
|
// that could mess up the system like calling malloc() or free().
|
||||||
|
_ = inputBuffer;
|
||||||
|
_ = timeInfo; // TODO: Synchronize this to the rest of the world
|
||||||
|
_ = statusFlags;
|
||||||
|
_ = userData;
|
||||||
|
const out = @ptrCast([*]f32, @alignCast(4, outputBuffer));
|
||||||
|
for(0..framesPerBuffer) |i| {
|
||||||
|
out[2*i] = musicData[curIndex];
|
||||||
|
out[2*i+1] = musicData[curIndex+1];
|
||||||
|
curIndex = (curIndex + 2)%musicData.len;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -3,6 +3,7 @@ const std = @import("std");
|
|||||||
pub const gui = @import("gui");
|
pub const gui = @import("gui");
|
||||||
pub const server = @import("server");
|
pub const server = @import("server");
|
||||||
|
|
||||||
|
pub const audio = @import("audio.zig");
|
||||||
pub const assets = @import("assets.zig");
|
pub const assets = @import("assets.zig");
|
||||||
pub const blocks = @import("blocks.zig");
|
pub const blocks = @import("blocks.zig");
|
||||||
pub const chunk = @import("chunk.zig");
|
pub const chunk = @import("chunk.zig");
|
||||||
@ -511,6 +512,9 @@ pub fn main() !void {
|
|||||||
try graphics.init();
|
try graphics.init();
|
||||||
defer graphics.deinit();
|
defer graphics.deinit();
|
||||||
|
|
||||||
|
try audio.init();
|
||||||
|
defer audio.deinit();
|
||||||
|
|
||||||
try gui.init();
|
try gui.init();
|
||||||
defer gui.deinit();
|
defer gui.deinit();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user