mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -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"]
|
||||
path = 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() });
|
||||
}
|
||||
}
|
||||
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("server", .{.source_file = .{.path = "src/server/server.zig"}});
|
||||
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 server = @import("server");
|
||||
|
||||
pub const audio = @import("audio.zig");
|
||||
pub const assets = @import("assets.zig");
|
||||
pub const blocks = @import("blocks.zig");
|
||||
pub const chunk = @import("chunk.zig");
|
||||
@ -511,6 +512,9 @@ pub fn main() !void {
|
||||
try graphics.init();
|
||||
defer graphics.deinit();
|
||||
|
||||
try audio.init();
|
||||
defer audio.deinit();
|
||||
|
||||
try gui.init();
|
||||
defer gui.deinit();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user