Last active
January 28, 2025 17:57
-
-
Save Staars/6eeb027941341985c5a9ea2162a4a55e to your computer and use it in GitHub Desktop.
unused i2s snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AudioEncoderOpus : public AudioEncoder | |
{ | |
public: | |
AudioEncoderOpus() { | |
AddLog(LOG_LEVEL_DEBUG,PSTR("I2S: AudioEncoderOpus")); | |
headerBuffer = (uint8_t*)&combHeader; | |
packetno = 0; | |
}; | |
virtual ~AudioEncoderOpus() { | |
if(inBuffer){ free(inBuffer); } | |
if(outFrame){ free(outFrame); } | |
opus_encoder_destroy(encoder); | |
}; | |
virtual uint32_t begin(uint32_t samplingRate, uint32_t inputChannels) { | |
int error; | |
encoder = opus_encoder_create(samplingRate, inputChannels, OPUS_APPLICATION_AUDIO, &error); | |
if (error != 0) { return error; } | |
opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(complexity)); | |
sigHead.samplingRate = samplingRate; | |
sigHead.inputChannels = inputChannels; | |
_makeHeader(); | |
constexpr uint32_t frameDuration = 20; //ms | |
samplesPerPass = samplingRate/(1000/frameDuration); | |
byteSize = samplesPerPass * 2 * inputChannels; | |
inBuffer = (int16_t*)malloc(byteSize); | |
if (!inBuffer) {return 5; } | |
outFrame = (uint8_t*)malloc(maxBytes); | |
if (!outFrame) {return 5; } | |
return 0; | |
}; | |
virtual size_t encode() { | |
opus_int32 i = opus_encode(encoder, inBuffer, samplesPerPass, outFrame, maxBytes); | |
return i; | |
} | |
virtual size_t getHeaderSize() { | |
return sizeof(combHeader); | |
} | |
protected: | |
OpusEncoder *encoder; | |
const uint32_t maxBytes = 1296; | |
const uint32_t complexity = 1; // 1-10 - low to high quality | |
struct __attribute__((packed)) { | |
ogg_packet sigHead; | |
ogg_packet sigTags; | |
} combHeader; | |
uint32_t packetno; | |
struct __attribute__((packed)) { | |
char signatureHead[8] = {'O', 'p', 'u', 's', 'H', 'e', 'a', 'd'}; | |
uint8_t version = 1; | |
uint8_t inputChannels = 0; | |
uint16_t preSkip = 3840; | |
uint32_t samplingRate = 0; | |
int16_t outputGain = 0; | |
uint8_t channelMappingFamily = 0; | |
} sigHead; | |
struct __attribute__((packed)) { | |
char signatureTags[8] = {'O', 'p', 'u', 's', 'T', 'a', 'g', 's'}; | |
uint32_t vendorStringLength = 8; | |
char vendor[8] = "Tasmota"; | |
uint32_t userCommentListLength = 0; | |
} sigTags; | |
void _makeHeader(){ | |
combHeader.sigHead.packet = (uint8_t *)&sigHead; | |
combHeader.sigHead.bytes = sizeof(sigHead); | |
combHeader.sigHead.granulepos = 0; | |
combHeader.sigHead.packetno = packetno++; | |
combHeader.sigHead.b_o_s = true; | |
combHeader.sigHead.e_o_s = false; | |
combHeader.sigTags.packet = (uint8_t *)&sigTags; | |
combHeader.sigTags.bytes = sizeof(sigTags); | |
combHeader.sigTags.granulepos = 0; | |
combHeader.sigTags.packetno = packetno++; | |
combHeader.sigTags.b_o_s = true; | |
combHeader.sigTags.e_o_s = false; | |
} | |
}; | |
#include "libopus/opus.h" | |
#include "libopusenc/include/opusenc.h" | |
class AudioEncoderOpusOPE; | |
typedef int (AudioEncoderOpusOPE::*packet_write)(void *userdata, const unsigned char *ptr, int len); | |
typedef int (AudioEncoderOpusOPE::*packet_close)(void *userdata); | |
class AudioEncoderOpusOPE : public AudioEncoder | |
{ | |
public: | |
AudioEncoderOpusOPE(File *rec_file, WiFiClient *wifi) { | |
file = rec_file; | |
client = wifi; | |
comments = ope_comments_create(); | |
receivedFrames = 0; | |
ope_comments_add(comments, "TASMOTA", "14.x"); | |
}; | |
virtual ~AudioEncoderOpusOPE() { | |
ope_comments_destroy(comments); | |
ope_encoder_destroy(enc); | |
if(file) {file->close();} | |
if(client) {client->stop();} | |
}; | |
virtual uint32_t begin(uint32_t samplingRate, uint32_t inputChannels) { | |
if(callbacks.write == nullptr){ | |
return 6; | |
} | |
int error; | |
enc = ope_encoder_create_callbacks(&callbacks, (void *)this, comments, samplingRate, inputChannels, 0, &error); | |
if(enc == nullptr) {return 3;} | |
ope_encoder_ctl(enc, OPUS_SET_COMPLEXITY_REQUEST, 0); | |
constexpr uint32_t frameDuration = 20; //ms | |
samplesPerPass = samplingRate/(1000/frameDuration); | |
byteSize = samplesPerPass * 2 * inputChannels; | |
inBuffer = (int16_t*)malloc(byteSize); | |
if (!inBuffer) {return 5; } | |
outFrame = (uint8_t*)malloc(maxBytes); | |
if (!outFrame) {return 5; } | |
return 0; | |
}; | |
virtual int encode(size_t samples) { | |
receivedFrames += 1; | |
if( receivedFrames > 25){ //about 0.5 seconds for 20ms frames | |
ope_encoder_flush(enc); | |
receivedFrames = 0; | |
} | |
return ope_encoder_write(enc, inBuffer, samples); | |
} | |
virtual size_t stop() { | |
return ope_encoder_drain(enc); | |
} | |
virtual void setCB(void *cb){ | |
OpusEncCallbacks * _cb = (OpusEncCallbacks *)cb; | |
callbacks.write = _cb->write; | |
callbacks.close = _cb->close; | |
} | |
static int packet_write(void *userdata, const unsigned char *ptr, opus_int32 len){ | |
AudioEncoderOpusOPE *enc = (AudioEncoderOpusOPE*)userdata; | |
size_t written = 0; | |
if(enc->file != nullptr){ | |
written = enc->file->write(ptr,len); | |
} else if (enc->client != nullptr){ | |
written = enc->client->write(ptr,len); | |
} | |
return (written != (size_t)len); | |
} | |
static int packet_close(void *userdata){ | |
(void)userdata; | |
return 0; | |
} | |
protected: | |
OpusEncCallbacks callbacks; | |
OggOpusEnc *enc; | |
OggOpusComments *comments; | |
size_t receivedFrames ; | |
const uint32_t maxBytes = 1296; | |
const uint32_t complexity = 1; // 1-10 - low to high quality | |
}; | |
void resample16to32(){ | |
// for(int32_t i = (samplesPerPass/2) - 1; i>=0; i--){ | |
// inBuffer[(i*2) + 1] = inBuffer[i]; | |
// if(i>0) inBuffer[(i*2)] = ((int32_t)inBuffer[i] + (int32_t)inBuffer[i-1]) / 2; | |
// } | |
int16_t* dst = inBuffer + (samplesPerPass - 1); | |
int16_t* src = inBuffer + ((samplesPerPass/2) - 1); | |
src[1] = 0; //guess the direction of the next frame heading zero | |
while (dst > inBuffer){ | |
int32_t averaged = ((int32_t)*src + (int32_t)*(src + 1))/2; | |
*dst-- = averaged; | |
*dst-- = *src--; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment