-
Notifications
You must be signed in to change notification settings - Fork 0
/
mp3.c
114 lines (92 loc) · 3.54 KB
/
mp3.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/******************************************************************************
* Copyright (c) 2011 Hanna Reitz *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
******************************************************************************/
#include <mpg123.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "player.h"
struct mp3_format
{
struct file_type ft;
mpg123_handle *mh;
double tpf;
};
static bool is_mp3(FILE *fp, struct file_type **ft)
{
mpg123_init();
int err;
mpg123_handle *mh = mpg123_new(NULL, &err);
if (mh == NULL)
{
fprintf(stderr, "Could not create mpg123 handle: %s\n", mpg123_plain_strerror(err));
return false;
}
long pos = ftell(fp);
if (mpg123_open_fd(mh, fileno(fp)) != MPG123_OK)
{
fseek(fp, pos, SEEK_SET);
return false;
}
mpg123_scan(mh);
struct mpg123_frameinfo fi;
mpg123_info(mh, &fi);
if (mpg123_format(mh, fi.rate, MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK)
{
fseek(fp, pos, SEEK_SET);
return false;
}
off_t length = mpg123_length(mh);
struct mp3_format *fmt = calloc(sizeof(*fmt), 1);
*ft = &fmt->ft;
fmt->mh = mh;
fmt->tpf = mpg123_tpf(mh);
fmt->ft.channels = 2;
fmt->ft.position = 0;
fmt->ft.length = (length + (fi.rate / 2)) / fi.rate;
fmt->ft.sample_rate = fi.rate;
fmt->ft.sample_size = 2;
fmt->ft.sample_type = ST_SIGNED_INTEGER_LE;
fmt->ft.bitrate = (double)fi.abr_rate;
return true;
}
static size_t dec_mp3(struct file_type *ft, size_t out_frames, void *out_buf)
{
size_t cdone = 0;
struct mp3_format *mp3 = (struct mp3_format *)ft;
int ret;
do
{
size_t bdone;
ret = mpg123_read(mp3->mh, out_buf, (out_frames - cdone) * 4, &bdone);
cdone += bdone / 4;
}
while ((cdone < out_frames) && (ret != MPG123_DONE) && (ret <= 0));
ft->position = (volatile int)(mpg123_tellframe(mp3->mh) * mp3->tpf);
return cdone;
}
static const struct decoder mp3 = {
.name = "MP3",
.check_file = &is_mp3,
.decode = &dec_mp3
};
DEFINE_DC(&mp3)