audiocogs / mp3.js

A JavaScript MP3 decoder for Aurora.js
http://audiocogs.org/codecs/mp3
263 stars 45 forks source link

Decode frame before browser play mp3 with my algorithm. #17

Open ajenkul opened 8 years ago

ajenkul commented 8 years ago

I'm using ffmpeg in C for my Android project. It works perfect till Google release lasted NDK, all my library broken now. Then I decided to switch my project to hybrid app, using javascript as a development. I found this repo which help me decode/encode mp3 file. The problem is, I have a lot of audio encoded by my algorithm, now I want to use ffmpeg in javascript to decode it before it can play in the browser. Please give me some suggestion, thanks you! UPDATE: I just want to decode the main data in each frame by XOR its bit with my hexa number. Because my mp3 file is encoded data only on each frame (not metadata). Please help me find where in your source code can loop through and decode it.

ajenkul commented 8 years ago

@devongovett @thijstriemstra @qzchenwl @mjibson @duckinator Could you please give me a minutes for my problem?

thijstriemstra commented 8 years ago

Spamming random contributors of a project is not a good idea wtf

ajenkul commented 8 years ago

I'm so sorry, because I have no idea how to solve this.

devongovett commented 8 years ago

I have no idea what you're trying to do.

ajenkul commented 8 years ago

Hi, very happy when see your comment. Let me describe it more clearly. I'm going to xor (^) every bit from the 32th to the end of a frame by 0x40 before the function decodeMainData is invoked (or before the player can read and play it). Because my mp3 file has been XORed by 0x40 in the data part (not header nor metadata, it come from bit 32th). I found this function that can detect the range of each frame, but get no luck to get it play after XOR it again by 0x40 to get the original bits. This is the function i found that I think it could help me.

55 Layer3.prototype.decode = function(stream, frame) { 
56     var header = frame.header; 
57     var next_md_begin = 0; 
58     var md_len = 0; 
59      
60     var nch = header.nchannels(); 
61     var si_len = (header.flags & MP3FrameHeader.FLAGS.LSF_EXT) ? (nch === 1 ? 9 : 17) : (nch === 1 ? 17 : 32); 
62          
63     // check frame sanity 
64     if (stream.next_frame - stream.nextByte() < si_len) { 
65         stream.md_len = 0; 
66         throw new Error('Bad frame length'); 
67     } 
68      
69     // check CRC word 
70     if (header.flags & MP3FrameHeader.FLAGS.PROTECTION) { 
71         // TODO: crc check 
72     } 
73      
74     // decode frame side information 
75     var sideInfo = this.sideInfo(stream, nch, header.flags & MP3FrameHeader.FLAGS.LSF_EXT);         
76     var si = sideInfo.si; 
77     var data_bitlen = sideInfo.data_bitlen; 
78     var priv_bitlen = sideInfo.priv_bitlen; 
79      
80     header.flags        |= priv_bitlen; 
81     header.private_bits |= si.private_bits; 
82      
83     // find main_data of next frame 
84     var peek = stream.copy(); 
85     peek.seek(stream.next_frame * 8); 
86      
87     var nextHeader = peek.read(16);     
88     if ((nextHeader & 0xffe6) === 0xffe2) { // syncword | layer 
89         if ((nextHeader & 1) === 0) // protection bit 
90             peek.advance(16); // crc check 
91              
92         peek.advance(16); // skip the rest of the header 
93         next_md_begin = peek.read((nextHeader & 8) ? 9 : 8); 
94     } 
95      
96     // find main_data of this frame 
97     var frame_space = stream.next_frame - stream.nextByte(); 
98      
99     if (next_md_begin > si.main_data_begin + frame_space) 
100         next_md_begin = 0; 
101          
102     var md_len = si.main_data_begin + frame_space - next_md_begin; 
103     var frame_used = 0; 
104     var ptr; 
105      
106     if (si.main_data_begin === 0) { 
107         ptr = stream.stream; 
108         stream.md_len = 0; 
109         frame_used = md_len; 
110     } else { 
111         if (si.main_data_begin > stream.md_len) { 
112             throw new Error('bad main_data_begin pointer'); 
113         } else { 
114             var old_md_len = stream.md_len; 
115              
116             if (md_len > si.main_data_begin) { 
117                 if (stream.md_len + md_len - si.main_data_begin > MP3FrameHeader.BUFFER_MDLEN) { 
118                     throw new Error("Assertion failed: (stream.md_len + md_len - si.main_data_begin <= MAD_MP3FrameHeader.BUFFER_MDLEN)"); 
119                 } 
120                  
121                 frame_used = md_len - si.main_data_begin; 
122                 this.memcpy(stream.main_data, stream.md_len, stream.stream.stream, stream.nextByte(), frame_used); 
123                 stream.md_len += frame_used; 
124             } 
125              
126             ptr = new AV.Bitstream(AV.Stream.fromBuffer(new AV.Buffer(stream.main_data))); 
127             ptr.advance((old_md_len - si.main_data_begin) * 8); 
128         } 
129     } 
130      
131     var frame_free = frame_space - frame_used; 
132      
133     // decode main_data 
134     this.decodeMainData(ptr, frame, si, nch); 
135      
136     // preload main_data buffer with up to 511 bytes for next frame(s) 
137     if (frame_free >= next_md_begin) { 
138         this.memcpy(stream.main_data, 0, stream.stream.stream, stream.next_frame - next_md_begin, next_md_begin); 
139         stream.md_len = next_md_begin; 
140     } else { 
141         if (md_len < si.main_data_begin) { 
142             var extra = si.main_data_begin - md_len; 
143             if (extra + frame_free > next_md_begin) 
144                 extra = next_md_begin - frame_free; 
145 

146             if (extra < stream.md_len) { 
147                 this.memcpy(stream.main_data, 0, stream.main_data, stream.md_len - extra, extra); 
148                 stream.md_len = extra; 
149             } 
150         } else { 
151             stream.md_len = 0; 
152         } 
153          
154         this.memcpy(stream.main_data, stream.md_len, stream.stream.stream, stream.next_frame - frame_free, frame_free); 
155         stream.md_len += frame_free; 
156     } 
157 }; 

And this is the block of codes I have tried to inject in but I have no luck:

    for (var i = stream.this_frame+32; i<stream.next_frame; i++{
        stream.stream.stream.list.first.data[i] ^= 0x40;
    }

This is the demo XORed file.