-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathencodeMp3.c
135 lines (117 loc) · 3.32 KB
/
encodeMp3.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <emscripten/bind.h>
#include <emscripten.h>
#include <lame/lame.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <fstream>
#define MAX_ENCODE_SAMLES 65536 * 8
#define BUFFER_SIZE (MAX_ENCODE_SAMLES * 1.25 + 7200)
typedef enum
{
VBR_METHOD_NONE = 0,
VBR_METHOD_DEFAULT = 1,
VBR_METHOD_ABR = 2
} vbrMethod_e;
extern "C" EMSCRIPTEN_KEEPALIVE
ssize_t encode(int rate, int channels, int bitrate, vbrMethod_e vbrMethod, int nsamples) {
lame_global_flags* pgf = lame_init();
if (!pgf) {
free(pgf);
return -1;
}
lame_set_in_samplerate(pgf, rate);
lame_set_num_channels(pgf, channels);
switch (vbrMethod) {
case VBR_METHOD_NONE:
lame_set_VBR(pgf, vbr_off);
break;
case VBR_METHOD_ABR:
lame_set_VBR(pgf, vbr_abr);
break;
case VBR_METHOD_DEFAULT:
default:
lame_set_VBR(pgf, vbr_default);
break;
};
lame_set_brate(pgf, bitrate);
ssize_t ret;
ret = lame_init_params(pgf);
if (ret == -1) {
free(pgf);
return -2;
}
printf("nsamples: %d\n", nsamples);
int m_outOffset = 0;
int chunkStart = 0;
unsigned char* mp3buf = (unsigned char*)malloc(1.25 * nsamples + 7200);
std::ifstream isL ("audioBufferL", std::ifstream::binary);
std::ifstream isR ("audioBufferR", std::ifstream::binary);
while (chunkStart < nsamples) {
if (!isL) {
free(pgf);
free(mp3buf);
if (isL) isL.close();
if (isR) isR.close();
return -3;
}
int chunkEnd = std::min(chunkStart + MAX_ENCODE_SAMLES, nsamples);
int chunkLength = chunkEnd - chunkStart;
int out_bytes = 0;
float* pcm_l = new float [chunkLength];
isL.read ((char*)pcm_l, chunkLength * sizeof(float));
int pcm_r_length = 0;
if (channels == 2 && isR)
pcm_r_length = chunkLength;
float* pcm_r = new float [pcm_r_length];
if (isR)
isR.read ((char*)pcm_r, chunkLength * sizeof(float));
out_bytes = lame_encode_buffer_ieee_float(pgf, pcm_l, pcm_r,
chunkLength,
mp3buf + m_outOffset, BUFFER_SIZE);
delete[] pcm_l;
delete[] pcm_r;
if (out_bytes < 0){
free(pgf);
free(mp3buf);
if (isL) isL.close();
if (isR) isR.close();
return -4;
}
chunkStart = chunkEnd;
m_outOffset += out_bytes;
EM_ASM({
const progress = $0;
const elm = document.getElementsByClassName('progress-bar').item(0);
if (elm){
const pcg = Math.round(progress * 100);
elm.setAttribute('aria-valuenow',pcg);
elm.setAttribute('style','width:'+Number(pcg)+'%');
elm.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated');
elm.innerText = Number(pcg)+'%';
}
}, float(chunkEnd) / float(nsamples));
emscripten_sleep(1);
}
if (isL) {
isL.close();
std::remove("audioBufferL");
}
if (isR) {
isR.close();
std::remove("audioBufferR");
}
FILE *file;
printf("Write File\n");
file = fopen("output.mp3", "w");
fwrite(mp3buf, sizeof mp3buf[0], m_outOffset, file);
fclose(file);
free(pgf);
free(mp3buf);
printf("Complete\n");
return 1;
}
EMSCRIPTEN_BINDINGS() {
emscripten::function("encode", &encode);
}