kopia lustrzana https://github.com/bitluni/ESP32AMRadioTransmitter
added projects
rodzic
1c4cf45e1a
commit
f7a56e8af4
|
@ -0,0 +1,70 @@
|
|||
//code by bitluni (send me a high five if you like the code)
|
||||
|
||||
//replace this include file by your header file generated by the conversion tool
|
||||
#include "sample.h"
|
||||
|
||||
#include <soc/rtc.h>
|
||||
#include "driver/i2s.h"
|
||||
|
||||
static const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM_0; // i2s port number
|
||||
|
||||
//static i2s_config_t i2s_config;
|
||||
static const i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
|
||||
.sample_rate = 1000000, //not really used
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024 //big buffers to avoid noises
|
||||
};
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); //highest cpu frequency
|
||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //start i2s driver
|
||||
i2s_set_pin(i2s_num, NULL); //use internal DAC
|
||||
i2s_set_sample_rates(i2s_num, 1000000); //dummy sample rate, since the function fails at high values
|
||||
|
||||
//this is the hack that enables the highest sampling rate possible ~13MHz, have fun
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_A_V, 1, I2S_CLKM_DIV_A_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_B_V, 1, I2S_CLKM_DIV_B_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_NUM_V, 2, I2S_CLKM_DIV_NUM_S);
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_TX_BCK_DIV_NUM_V, 2, I2S_TX_BCK_DIV_NUM_S);
|
||||
}
|
||||
|
||||
//buffer to store modulated samples
|
||||
short buff[1024];
|
||||
//sine represented in 16 values. at 13MHz sampling rate the resulting carrier is at around 835KHz
|
||||
int sintab[] = {0, 48, 90, 117, 127, 117, 90, 48, 0, -48, -90, -117, -127, -117, -90, -48};
|
||||
|
||||
unsigned long long pos = 0; //current position in the audio sample, using fixed point
|
||||
unsigned int posLow = 0;
|
||||
unsigned long long posInc = ((unsigned long long)sampleRate << 32) / 835000; //sample fixed increment
|
||||
|
||||
void loop()
|
||||
{
|
||||
//fill the sound buffer
|
||||
for(int i = 0; i < 1024; i+=16)
|
||||
{
|
||||
if(posLow >= sampleCount) posLow = sampleCount - 1;
|
||||
//taking current sample
|
||||
int s = samples[posLow] + 128;
|
||||
//modulating that sample on the 16 values of the carrier wave (respect to I2S byte order, 16Bit/Sample)
|
||||
for(int j = 0; j < 16; j += 4)
|
||||
{
|
||||
buff[i + j + 1] = (sintab[j + 0] * s + 0x8000);
|
||||
buff[i + j + 0] = (sintab[j + 1] * s + 0x8000);
|
||||
buff[i + j + 3] = (sintab[j + 2] * s + 0x8000);
|
||||
buff[i + j + 2] = (sintab[j + 3] * s + 0x8000);
|
||||
}
|
||||
pos += posInc;
|
||||
posLow = pos >> 32;
|
||||
if(posLow >= sampleCount)
|
||||
pos = posLow = 0;
|
||||
}
|
||||
//write the buffer (waits until a buffer is ready to be filled, that's timing for free)
|
||||
i2s_write_bytes(i2s_num, (char*)buff, 2048, portMAX_DELAY);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
[LocalizedFileNames]
|
||||
nightsession.h=@nightsession.h,0
|
||||
nightsession (1).h=@nightsession (1).h,0
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,81 @@
|
|||
//code by bitluni (send me a high five if you like the code)
|
||||
|
||||
//replace this include file by your header file generated by the conversion tool
|
||||
#include "sample.h"
|
||||
|
||||
//The pin where the button is connected to:
|
||||
const int BUTTON_PIN = 18;
|
||||
//(the button is connected between that pin and ground. the button is using the internal pullup)
|
||||
|
||||
|
||||
#include <soc/rtc.h>
|
||||
#include "driver/i2s.h"
|
||||
|
||||
static const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM_0; // i2s port number
|
||||
|
||||
//static i2s_config_t i2s_config;
|
||||
static const i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
|
||||
.sample_rate = 1000000, //not really used
|
||||
.bits_per_sample = (i2s_bits_per_sample_t)I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 2,
|
||||
.dma_buf_len = 1024 //big buffers to avoid noises
|
||||
};
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||
Serial.begin(115200);
|
||||
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); //highest cpu frequency
|
||||
i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //start i2s driver
|
||||
i2s_set_pin(i2s_num, NULL); //use internal DAC
|
||||
i2s_set_sample_rates(i2s_num, 1000000); //dummy sample rate, since the function fails at high values
|
||||
|
||||
//this is the hack that enables the highest sampling rate possible ~13MHz, have fun
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_A_V, 1, I2S_CLKM_DIV_A_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_B_V, 1, I2S_CLKM_DIV_B_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_NUM_V, 2, I2S_CLKM_DIV_NUM_S);
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_TX_BCK_DIV_NUM_V, 2, I2S_TX_BCK_DIV_NUM_S);
|
||||
}
|
||||
|
||||
//buffer to store modulated samples
|
||||
short buff[1024];
|
||||
//sine represented in 16 values. at 13MHz sampling rate the resulting carrier is at around 835KHz
|
||||
int sintab[] = {0, 48, 90, 117, 127, 117, 90, 48, 0, -48, -90, -117, -127, -117, -90, -48};
|
||||
|
||||
unsigned long long pos = 0; //current position in the audio sample, using fixed point
|
||||
unsigned int posLow = sampleCount; //set postion to end of sample to not play at reset
|
||||
unsigned long long posInc = ((unsigned long long)sampleRate << 32) / 835000; //sample fixed increment
|
||||
|
||||
void loop()
|
||||
{
|
||||
//reset sample position when button is down
|
||||
if(!digitalRead(BUTTON_PIN))
|
||||
pos = posLow = 0;
|
||||
|
||||
//fill the sound buffer
|
||||
for(int i = 0; i < 1024; i+=16)
|
||||
{
|
||||
if(posLow >= sampleCount) posLow = sampleCount - 1;
|
||||
//taking current sample
|
||||
int s = samples[posLow] + 128;
|
||||
//modulating that sample on the 16 values of the carrier wave (respect to I2S byte order, 16Bit/Sample)
|
||||
for(int j = 0; j < 16; j += 4)
|
||||
{
|
||||
buff[i + j + 1] = (sintab[j + 0] * s + 0x8000);
|
||||
buff[i + j + 0] = (sintab[j + 1] * s + 0x8000);
|
||||
buff[i + j + 3] = (sintab[j + 2] * s + 0x8000);
|
||||
buff[i + j + 2] = (sintab[j + 3] * s + 0x8000);
|
||||
}
|
||||
if(posLow < sampleCount - 1)
|
||||
{
|
||||
pos += posInc;
|
||||
posLow = pos >> 32;
|
||||
}
|
||||
}
|
||||
//write the buffer (waits until a buffer is ready to be filled, that's timing for free)
|
||||
i2s_write_bytes(i2s_num, (char*)buff, 2048, portMAX_DELAY);
|
||||
}
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,89 @@
|
|||
<head>
|
||||
<script>
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
var context = new AudioContext();
|
||||
|
||||
function audioBufferToText(audioBuffer, normalize, resample, sampleRate)
|
||||
{
|
||||
var buffer = audioBuffer.getChannelData(0);
|
||||
|
||||
if(audioBuffer.numberOfChannels > 1)
|
||||
{
|
||||
for(var c = 1; c < audioBuffer.numberOfChannels; c++)
|
||||
{
|
||||
var cb = audioBuffer.getChannelData(c);
|
||||
for(var i = 0; i < length; i++)
|
||||
buffer[i] += cb[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(resample)
|
||||
{
|
||||
var scale = audioBuffer.sampleRate / sampleRate;
|
||||
var length = Math.floor((buffer.length - 1) / scale);
|
||||
var b = new Float32Array(length);
|
||||
for(var i = 0; i < length; i++)
|
||||
{
|
||||
p = Math.floor(i * scale);
|
||||
b[i] = buffer[p];
|
||||
}
|
||||
buffer = b;
|
||||
}
|
||||
else
|
||||
sampleRate = audioBuffer.sampleRate;
|
||||
|
||||
var text = "const unsigned int sampleRate = " + sampleRate + ";\r\n";
|
||||
text += "const unsigned int sampleCount = " + buffer.length + ";\r\n";
|
||||
text += "const signed char samples[] = {"
|
||||
|
||||
var max = 0;
|
||||
if(normalize)
|
||||
for(var i = 0; i < buffer.length; i++)
|
||||
max = Math.max(Math.abs(buffer[i]), max);
|
||||
if(max == 0) max = 1;
|
||||
for(var i = 0; i < buffer.length; i++)
|
||||
{
|
||||
if((i & 15) == 0) text += "\r\n";
|
||||
text += Math.round(buffer[i] / max * 127) + ", ";
|
||||
}
|
||||
text += "};\r\n";
|
||||
return text;
|
||||
}
|
||||
//isn't that simple code awesome? ...that's bitluni style
|
||||
|
||||
function enrickSound(buffer)
|
||||
{
|
||||
//if you are looking for this function.. sorry that was a gag
|
||||
}
|
||||
|
||||
function convert(event)
|
||||
{
|
||||
var audioBuffer = null;
|
||||
var reader = new FileReader();
|
||||
var file = event.target.files[0];
|
||||
reader.onload = function(){
|
||||
context.decodeAudioData(reader.result, function(buffer) {
|
||||
var link = document.createElement("a");
|
||||
link.download = file.name.split('.', 1)[0] + ".h";
|
||||
link.href = URL.createObjectURL(new Blob(
|
||||
[audioBufferToText(buffer, document.getElementById("normalize").checked, document.getElementById("resample").checked, document.getElementById("samplerate").value)], {type: "text/plain"}));
|
||||
document.body.appendChild(document.createElement("br"));
|
||||
document.body.appendChild(link);
|
||||
link.innerHTML = link.download;
|
||||
link.click();
|
||||
//document.body.removeChild(link);
|
||||
event.target.value = "";
|
||||
}, function(){
|
||||
//error
|
||||
});
|
||||
}
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="font-family: arial">
|
||||
<h1><a href="https://youtube.com/bitlunislab">bitluni</a>'s audio to header converter</h1>
|
||||
Open an audio file supported by the browser to convert it to a c++ header file (8Bit signed).<br><br>
|
||||
<input type="file" onchange="convert(event)"><br><br>
|
||||
Export: <input id="normalize" type="checkbox" checked>normalize <input id="resample" type="checkbox">resample <input id="samplerate" value="11025"><br>
|
||||
</body></html>
|
Ładowanie…
Reference in New Issue