History

add opus support

Sigrid Solveig Haflínudóttir committed 6 years ago

Commit 54dcc131 parent 5feb1805 files · +98 −0Browse files

Unified · Split

5 files
  1. README.md +1 −0
  2. mkfile +1 −0
  3. opus.c +93 −0
  4. tags.c +2 −0
  5. tags.h +1 −0
README.md+1−0
@@ -11,6 +11,7 @@ Comparison to id3lib and taglib: · 10 unmodified lines
1111 | Ogg/Vorbis | yes | no | yes |
1212 | FLAC | yes | no | yes |
1313 | m4a | yes | no | yes |
14+| opus | yes | no | yes |
1415 | replay gain | yes | no | ??? |
1516 | size | tiny | bloated | more bloated |
1617 | license | PPL | LGPL | LGPL/MPL |
mkfile+1−0
@@ -8,6 +8,7 @@ OFILES=\ · 7 unmodified lines
88 id3v1.$O\
99 id3v2.$O\
1010 m4a.$O\
11+ opus.$O\
1112 tags.$O\
1213 utf16.$O\
1314 vorbis.$O\
opus.c+93−0
@@ -0,0 +1,93 @@
1+#include "tagspriv.h"
2+
3+#define leuint(d) (uint)(((uchar*)(d))[3]<<24 | ((uchar*)(d))[2]<<16 | ((uchar*)(d))[1]<<8 | ((uchar*)(d))[0]<<0)
4+
5+int
6+tagopus(Tagctx *ctx)
7+{
8+ char *v;
9+ uchar *d, h[4];
10+ int sz, numtags, i, npages;
11+
12+ d = (uchar*)ctx->buf;
13+ /* need to find vorbis frame with type=3 */
14+ for(npages = 0; npages < 2; npages++){ /* vorbis comment is the second header */
15+ int nsegs;
16+ if(ctx->read(ctx, d, 27) != 27)
17+ return -1;
18+ if(memcmp(d, "OggS", 4) != 0)
19+ return -1;
20+
21+ /* calculate the size of the packet */
22+ nsegs = d[26];
23+ if(ctx->read(ctx, d, nsegs+8) != nsegs+8)
24+ return -1;
25+ for(sz = i = 0; i < nsegs; sz += d[i++]);
26+
27+ if(memcmp(&d[nsegs], "OpusHead", 8) == 0){
28+ if(ctx->read(ctx, d, 8) != 8 || d[0] != 1)
29+ return -1;
30+ sz -= 8;
31+ ctx->channels = d[1];
32+ ctx->samplerate = leuint(&d[4]);
33+ }else if(memcmp(&d[nsegs], "OpusTags", 8) == 0){
34+ break;
35+ }
36+
37+ ctx->seek(ctx, sz-8, 1);
38+ }
39+
40+ if(npages < 3){
41+ if(ctx->read(ctx, d, 4) != 4)
42+ return -1;
43+ sz = leuint(d);
44+ if(ctx->seek(ctx, sz, 1) < 0 || ctx->read(ctx, h, 4) != 4)
45+ return -1;
46+ numtags = leuint(h);
47+
48+ for(i = 0; i < numtags; i++){
49+ if(ctx->read(ctx, h, 4) != 4)
50+ return -1;
51+ if((sz = leuint(h)) < 0)
52+ return -1;
53+
54+ if(ctx->bufsz < sz+1){
55+ if(ctx->seek(ctx, sz, 1) < 0)
56+ return -1;
57+ continue;
58+ }
59+ if(ctx->read(ctx, ctx->buf, sz) != sz)
60+ return -1;
61+ ctx->buf[sz] = 0;
62+
63+ if((v = strchr(ctx->buf, '=')) == nil)
64+ return -1;
65+ *v++ = 0;
66+ cbvorbiscomment(ctx, ctx->buf, v);
67+ }
68+ }
69+
70+ /* calculate the duration */
71+ if(ctx->samplerate > 0){
72+ sz = ctx->bufsz <= 4096 ? ctx->bufsz : 4096;
73+ for(i = sz; i < 65536+16; i += sz - 16){
74+ if(ctx->seek(ctx, -i, 2) <= 0)
75+ break;
76+ v = ctx->buf;
77+ if(ctx->read(ctx, v, sz) != sz)
78+ break;
79+ for(; v != nil && v < ctx->buf+sz;){
80+ v = memchr(v, 'O', ctx->buf+sz - v - 14);
81+ if(v != nil && v[1] == 'g' && v[2] == 'g' && v[3] == 'S' && (v[5] & 4) == 4){ /* last page */
82+ uvlong g = leuint(v+6) | (uvlong)leuint(v+10)<<32;
83+ ctx->duration = g * 1000 / ctx->samplerate;
84+ return 0;
85+ }
86+ if(v != nil)
87+ v++;
88+ }
89+ }
90+ }
91+
92+ return 0;
93+}
tags.c+2−0
@@ -13,6 +13,7 @@ extern int tagflac(Tagctx *ctx); · 12 unmodified lines
1313 extern int tagid3v2(Tagctx *ctx);
1414 extern int tagid3v1(Tagctx *ctx);
1515 extern int tagm4a(Tagctx *ctx);
16+extern int tagopus(Tagctx *ctx);
1617
1718 static const Getter g[] =
1819 {
@@ -21,6 +22,7 @@ static const Getter g[] = · 2 unmodified lines
2122 {tagvorbis, Fogg},
2223 {tagflac, Fflac},
2324 {tagm4a, Fm4a},
25+ {tagopus, Fopus},
2426 };
2527
2628 void
tags.h+1−0
@@ -30,6 +30,7 @@ enum · 29 unmodified lines
3030 Fogg,
3131 Fflac,
3232 Fm4a,
33+ Fopus,
3334 };
3435
3536 /* Tag parser context. You need to set it properly before parsing an audio file using libtags. */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t