Skip to content

Commit f13f38d

Browse files
committed
Add CircuitMess-Audio library
1 parent d334620 commit f13f38d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+25805
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea
2+
cmake-build-debug
3+
build
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name=CircuitMess Audio
2+
version=1.0.0
3+
author=CircuitMess
4+
maintainer=Filip Budiša <[email protected]>
5+
sentence=A handy library for audio playback, recording, and mixing.
6+
paragraph=Originally developed for the CircuitMess Jay-D
7+
category=Other
8+
url=https://github.com/CircuitMess/CircuitMess-Audio
9+
architectures=esp32
10+
includes=CMAudio.h
11+
depends=CircuitOS
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "Converter.h"
2+
#include "../Setup.hpp"
3+
4+
Converter::Converter(Source* source) : source(source){
5+
6+
}
7+
8+
Converter::~Converter(){
9+
}
10+
11+
size_t Converter::generate(int16_t* outBuffer){
12+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef JAYD_CONVERTER_H
2+
#define JAYD_CONVERTER_H
3+
4+
#include "Generator.h"
5+
#include "Source.h"
6+
7+
class Converter : public Generator {
8+
public:
9+
Converter(Source* source);
10+
~Converter();
11+
size_t generate(int16_t* outBuffer) override;
12+
13+
private:
14+
Source* source;
15+
16+
};
17+
18+
19+
#endif
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include "ID3Parser.h"
2+
3+
#define FLAG_UNSYNC 0b10000000
4+
#define FLAG_EHEAD 0b01000000
5+
#define FLAG_EXPER 0b00100000
6+
7+
#define FRAMEFLAG_COMP 0b10000000
8+
#define FRAMEFLAG_ENC 0b01000000
9+
10+
struct ID3Header {
11+
char id[3];
12+
uint8_t version;
13+
uint8_t revision;
14+
uint8_t flags;
15+
uint32_t size;
16+
} __attribute__((packed));
17+
18+
ID3Parser::ID3Parser(File& file) : file(file){ }
19+
20+
ID3Metadata ID3Parser::parse(){
21+
ID3Header header;
22+
23+
file.seek(0);
24+
file.read(reinterpret_cast<uint8_t*>(&header), sizeof(ID3Header));
25+
swendian(&header.size);
26+
sync(&header.size);
27+
28+
size = header.size;
29+
unsync = header.flags & FLAG_UNSYNC;
30+
extendedHeader = header.flags & FLAG_EHEAD;
31+
experimental = header.flags & FLAG_EXPER;
32+
33+
data = static_cast<uint8_t*>(malloc(size));
34+
file.read(data, size);
35+
dataPtr = 0;
36+
37+
if(extendedHeader){
38+
uint32_t ehSize = *reinterpret_cast<uint32_t*>(data);
39+
swendian(&ehSize);
40+
sync(&ehSize);
41+
42+
dataPtr += ehSize;
43+
}
44+
45+
ID3Metadata id3;
46+
id3.headerSize = size + 10;
47+
48+
while(dataPtr < size){
49+
if(data[dataPtr] != 'T'){
50+
printf("Error parsing ID3 header on byte %ld\n", dataPtr);
51+
free(data);
52+
return {};
53+
}
54+
55+
char frameID[3];
56+
memcpy(frameID, data + dataPtr + 1, 3);
57+
dataPtr += 4;
58+
59+
uint32_t frameSize = *reinterpret_cast<uint32_t*>(data + dataPtr);
60+
dataPtr += 4;
61+
62+
uint8_t frameTags1 = *reinterpret_cast<uint8_t*>(data + dataPtr);
63+
uint8_t frameTags2 = *reinterpret_cast<uint8_t*>(data + dataPtr + 1);
64+
dataPtr += 2;
65+
66+
swendian(&frameSize);
67+
if(unsync){
68+
sync(&frameSize);
69+
}
70+
71+
if((frameTags2 & FRAMEFLAG_COMP) || (frameTags2 & FRAMEFLAG_ENC)){
72+
dataPtr += frameSize;
73+
continue;
74+
}
75+
76+
char** field;
77+
if(memcmp(frameID, "IT2", 3) == 0){
78+
field = &id3.title;
79+
}else if(memcmp(frameID, "ALB", 3) == 0){
80+
field = &id3.album;
81+
}else if(memcmp(frameID, "PE1", 3) == 0){
82+
field = &id3.artist;
83+
}else{
84+
dataPtr += frameSize;
85+
continue;
86+
}
87+
88+
*field = static_cast<char*>(calloc(frameSize + 1, 1));
89+
memcpy(*field, data + dataPtr, frameSize);
90+
dataPtr += frameSize;
91+
92+
uint32_t dataStart;
93+
for(dataStart = 0; dataStart < frameSize && (*field)[dataStart] == 0; dataStart++);
94+
memcpy(*field, *field + dataStart, frameSize - dataStart);
95+
(*field)[frameSize - dataStart] = 0;
96+
}
97+
98+
free(data);
99+
return id3;
100+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#ifndef JAYD_ID3PARSER_H
2+
#define JAYD_ID3PARSER_H
3+
4+
#include <Arduino.h>
5+
#include <FS.h>
6+
7+
struct ID3Metadata {
8+
ID3Metadata(){}
9+
10+
size_t headerSize = 0;
11+
char* title = nullptr;
12+
char* album = nullptr;
13+
char* artist = nullptr;
14+
};
15+
16+
class ID3Parser {
17+
public:
18+
ID3Parser(fs::File& file);
19+
20+
ID3Metadata parse();
21+
22+
private:
23+
fs::File file;
24+
25+
bool unsync;
26+
bool extendedHeader;
27+
bool experimental;
28+
29+
uint8_t* data;
30+
size_t dataPtr = 0;
31+
size_t size; // without header
32+
33+
template<typename T>
34+
static void swendian(T* data){
35+
size_t swapped = 0;
36+
37+
for(int i = 0; i < sizeof(T); i++){
38+
swapped = (swapped << 8) | ((uint8_t*) data)[i];
39+
}
40+
41+
memcpy(data, &swapped, sizeof(T));
42+
}
43+
44+
template<typename T>
45+
static void sync(T* data){
46+
uint32_t mask = 0x7F;
47+
uint32_t value = *data & mask;
48+
mask = mask << 8;
49+
50+
for(int i = 1; i < sizeof(T); i++){
51+
value |= (value & mask) >> i;
52+
}
53+
54+
*data = value;
55+
}
56+
};
57+
58+
59+
#endif //JAYD_ID3PARSER_H

0 commit comments

Comments
 (0)