Created
July 5, 2024 13:34
-
-
Save makefunstuff/513e7e2cae68541e035bbed4f0700426 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <mpg123.h> | |
#include <alsa/asoundlib.h> | |
#define PCM_DEVICE "default" | |
int main(int argc, char *argv[]) { | |
if (argc < 2) { | |
printf("Usage: %s <mp3 file>\n", argv[0]); | |
return 1; | |
} | |
const char *filename = argv[1]; | |
// Initialize the MPG123 library | |
mpg123_init(); | |
mpg123_handle *mh = mpg123_new(NULL, NULL); | |
if (mpg123_open(mh, filename) != MPG123_OK) { | |
fprintf(stderr, "Error opening %s: %s\n", filename, mpg123_strerror(mh)); | |
return 1; | |
} | |
// Retrieve the format of the MP3 file | |
long rate; | |
int channels, encoding; | |
if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { | |
fprintf(stderr, "Error getting format: %s\n", mpg123_strerror(mh)); | |
return 1; | |
} | |
// Set the output format | |
snd_pcm_t *pcm_handle; | |
snd_pcm_hw_params_t *params; | |
int pcm; | |
snd_pcm_uframes_t frames; | |
char *buffer; | |
int size; | |
// Open the PCM device | |
if ((pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { | |
fprintf(stderr, "Error opening PCM device %s: %s\n", PCM_DEVICE, snd_strerror(pcm)); | |
return 1; | |
} | |
// Allocate hardware parameters object | |
snd_pcm_hw_params_alloca(¶ms); | |
snd_pcm_hw_params_any(pcm_handle, params); | |
// Set the desired hardware parameters | |
snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); | |
snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); | |
snd_pcm_hw_params_set_channels(pcm_handle, params, channels); | |
snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0); | |
// Write the parameters to the driver | |
if ((pcm = snd_pcm_hw_params(pcm_handle, params)) < 0) { | |
fprintf(stderr, "Error setting HW params: %s\n", snd_strerror(pcm)); | |
return 1; | |
} | |
// Decode and play the MP3 file | |
size_t buffer_size = mpg123_outblock(mh); | |
unsigned char *mpg123_buffer = (unsigned char *) malloc(buffer_size * sizeof(unsigned char)); | |
size_t done; | |
int err; | |
while ((err = mpg123_read(mh, mpg123_buffer, buffer_size, &done)) == MPG123_OK) { | |
// Convert the mpg123_buffer to the correct format and copy to the buffer | |
memcpy(buffer, mpg123_buffer, done); | |
snd_pcm_writei(pcm_handle, buffer, done / (channels * 2)); // 2 bytes/sample | |
} | |
// Clean up | |
free(buffer); | |
free(mpg123_buffer); | |
snd_pcm_drain(pcm_handle); | |
snd_pcm_close(pcm_handle); | |
mpg123_close(mh); | |
mpg123_delete(mh); | |
mpg123_exit(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const c = @cImport({ | |
@cInclude("mpg123.h"); | |
@cInclude("alsa/asoundlib.h"); | |
}); | |
pub fn brr(allocator: std.mem.Allocator, file: []const u8) !void { | |
_ = c.mpg123_init(); | |
const handle = c.mpg123_new(null, null) orelse { | |
std.log.warn("Failed to create mpg123 handle\n", .{}); | |
return; | |
}; | |
const file_path: [*c]const u8 = @ptrCast(file); | |
if (c.mpg123_open(handle, file_path) != c.MPG123_OK) { | |
std.log.warn("Failed to open the file: {s}\n", .{file_path}); | |
return; | |
} | |
var encoding: c_int = 0; | |
var channels: c_int = 0; | |
var rate: c_long = 0; | |
if (c.mpg123_getformat(handle, &rate, &channels, &encoding) != c.MPG123_OK) { | |
std.log.warn("Failed to get format\n", .{}); | |
return; | |
} | |
var pcm: ?*c.snd_pcm_t = undefined; | |
if (c.snd_pcm_open(&pcm, "default", c.SND_PCM_STREAM_PLAYBACK, 0) < 0) { | |
std.log.warn("Failed to open ALSA device\n", .{}); | |
return; | |
} | |
var dir: c_int = 0; | |
var params: ?*c.snd_pcm_hw_params_t = null; | |
if (c.snd_pcm_hw_params_malloc(¶ms) < 0) { | |
std.log.warn("Failed to allocate ALSA hardware parameters\n", .{}); | |
return; | |
} | |
_ = c.snd_pcm_hw_params_any(pcm, params); | |
_ = c.snd_pcm_hw_params(pcm, params); | |
_ = c.snd_pcm_hw_params_set_access(pcm, params, c.SND_PCM_ACCESS_RW_INTERLEAVED); | |
_ = c.snd_pcm_hw_params_set_format(pcm, params, c.SND_PCM_FORMAT_S16_LE); | |
_ = c.snd_pcm_hw_params_set_channels(pcm, params, @as(c_uint, @intCast(channels))); | |
_ = c.snd_pcm_hw_params_set_rate_near(pcm, params, @as(*c_uint, @ptrCast(&rate)), &dir); | |
if (c.snd_pcm_hw_params(pcm, params) < 0) { | |
std.log.warn("Failed to set ALSA hardware parameters\n", .{}); | |
return; | |
} | |
const buffer_size = c.mpg123_outblock(handle); | |
var done: usize = 0; | |
var mpg123_buffer: []u8 = try allocator.alloc(u8, buffer_size); | |
_ = &mpg123_buffer; | |
defer allocator.free(mpg123_buffer); | |
while (c.mpg123_read(handle, @as(?*anyopaque, @ptrCast(mpg123_buffer.ptr)), buffer_size, &done) == c.MPG123_OK) { | |
_ = c.snd_pcm_writei(pcm, @as(?*anyopaque, @ptrCast(mpg123_buffer.ptr)), done / 4); | |
} | |
_ = c.mpg123_delete(handle); | |
_ = c.snd_pcm_hw_params_free(params); | |
_ = c.snd_pcm_close(pcm); | |
_ = c.mpg123_exit(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment