Untitled
unknown
plain_text
2 years ago
4.6 kB
11
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <mad.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#include <id3.h>
pa_simple *device = NULL;
int ret = 1;
int error;
#define FIELD_BUFFER_SIZE 16
void output(struct mad_header const *header, struct mad_pcm *pcm);
void play(char* filename);
int print_meta(char* filename);
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "Usage: %s [filename.mp3] [filename.mp3] ...", argv[0]);
return 255;
}
// Set up PulseAudio 16-bit 44.100kHz stereo output
static const pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 };
if (!(device = pa_simple_new(NULL, "player", PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) {
printf("pa_simple_new() failed\n");
return 255;
}
for (int i = 1; i < argc; i++){
print_meta(argv[i]);
play(argv[i]);
}
if (device)
pa_simple_free(device);
return EXIT_SUCCESS;
}
void print_frame(char* name, ID3Frame* frame){
char buffer[FIELD_BUFFER_SIZE];
if(frame != NULL){
ID3Field *field = ID3Frame_GetField(frame, ID3FN_TEXT);
int size = ID3Field_Size(field);
ID3Field_GetASCII(field, buffer, size);
printf("%s: ", name);
printf(buffer);
printf("\n");
}
}
int print_meta(char* filename) {
ID3Tag *tag = ID3Tag_New();
printf("File Information\n");
printf(" Name: ");
printf(filename);
ID3Tag_Link(tag, filename);
ID3Frame* frame = ID3Tag_FindFrameWithID(tag, ID3FID_TITLE);
print_frame("\n Title", frame);
frame = ID3Tag_FindFrameWithID(tag, ID3FID_ALBUM);
print_frame(" Album", frame);
frame = ID3Tag_FindFrameWithID(tag, ID3FID_PERFORMERSORTORDER);
print_frame(" Performer", frame);
frame = ID3Tag_FindFrameWithID(tag, ID3FID_COMMENT);
print_frame(" Comments", frame);
}
void play(char* filename) {
// File pointer
FILE *fp = fopen(filename, "r");
int fd = fileno(fp);
// Fetch file size, etc
struct stat metadata;
if (fstat(fd, &metadata) >= 0) {
printf(" Size: %d Kbytes\n", (int)metadata.st_size / 1024);
} else {
printf("Failed to stat %s\n", filename);
fclose(fp);
}
printf("Playing\n");
char *input_stream = mmap(0, metadata.st_size, PROT_READ, MAP_SHARED, fd, 0);
// Decode frame and synthesize loop
struct mad_stream mad_stream;
struct mad_frame mad_frame;
struct mad_synth mad_synth;
mad_stream_init(&mad_stream);
mad_stream_buffer(&mad_stream, input_stream, metadata.st_size);
// Initialize MAD library
mad_synth_init(&mad_synth);
mad_frame_init(&mad_frame);
while (1) {
// Decode frame from the stream
if (mad_frame_decode(&mad_frame, &mad_stream)) {
if (MAD_RECOVERABLE(mad_stream.error)) {
continue;
} else if (mad_stream.error == MAD_ERROR_BUFLEN) {
continue;
} else {
break;
}
}
// Synthesize PCM data of frame
mad_synth_frame(&mad_synth, &mad_frame);
output(&mad_frame.header, &mad_synth.pcm);
}
fclose(fp);
mad_stream_finish(&mad_stream);
mad_synth_finish(&mad_synth);
mad_frame_finish(&mad_frame);
}
int scale(mad_fixed_t sample) {
sample += (1L << (MAD_F_FRACBITS - 16));
if (sample >= MAD_F_ONE)
sample = MAD_F_ONE - 1;
else if (sample < -MAD_F_ONE)
sample = -MAD_F_ONE;
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
void output(struct mad_header const *header, struct mad_pcm *pcm) {
register int nsamples = pcm->length;
mad_fixed_t const *left_ch = pcm->samples[0], *right_ch = pcm->samples[1];
static char stream[1152 * 4];
while (nsamples--) {
signed int sample;
sample = scale(*left_ch++);
stream[(pcm->length-nsamples) * 4 ] = ((sample >> 0) & 0xff);
stream[(pcm->length-nsamples) * 4 + 1] = ((sample >> 8) & 0xff);
sample = scale(*right_ch++);
stream[(pcm->length-nsamples) * 4 + 2 ] = ((sample >> 0) & 0xff);
stream[(pcm->length-nsamples) * 4 + 3] = ((sample >> 8) & 0xff);
}
if (pa_simple_write(device, stream, (size_t)1152 * 4, &error) < 0) {
fprintf(stderr, "pa_simple_write() failed: %s\n", pa_strerror(error));
return;
}
}Editor is loading...
Leave a Comment