LVGL Compile error “dram0.bss’ will not fit in region `dram0_0_seg’” with ILI9488 & ESP32 on Arduino Core - esp32

I constantly get this error, no matter what I'm doing... I have an ILI9488 with 4-wire SPI and a GT911 capacitive Touch driver on an ESP32 (2MB, no PSRAM, arduino core).
this is my main.ino-file:
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <Wire.h>
#include "Goodix.h"
#define INT_PIN 26
#define RST_PIN 15
#define SDA_PIN 22
#define SCL_PIN 16
Goodix touch = Goodix();
#define DISPLAY_BUF_SIZE 480 * 10
static uint16_t display_widht = 480;
static uint16_t display_height = 320;
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
bool touched = false;
GTPoint touchDat;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ DISPLAY_BUF_SIZE];
lv_disp_drv_t disp_drv; //display driver
lv_indev_drv_t touch_drv; //touchpad driver
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
}
void handleTouch(int8_t contacts, GTPoint* points) {
Serial.printf("Contacts: %d\n", contacts);
if(contacts > 0) touched = true;
else touched = false;
for (uint8_t i = 0; i < contacts; i++) {
touchDat = points[0];
Serial.printf("C%d: %d %d \n", points[i].trackId, points[i].x, points[i].y);
}
}
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * touch_drv, lv_indev_data_t * data ){
if( !touched ) //kein Touch
{
data->state = LV_INDEV_STATE_REL;
}
else //touch!
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touchDat.x;
data->point.y = touchDat.y;
}
}
void i2cInit(){
Wire.setPins(SDA_PIN, SCL_PIN);
Wire.setClock(400000);
Wire.begin();
delay(100);
}
void touchInit() {
touch.setHandler(handleTouch);
touch.setRes(display_widht, display_height);
touch.setRotation(3);
touch.begin(INT_PIN, RST_PIN, GOODIX_I2C_ADDR_28);
Serial.print("Check ACK on addr request on 0x");
Serial.print(touch.i2cAddr, HEX);
Wire.beginTransmission(touch.i2cAddr);
if (!Wire.endTransmission()) {
Serial.println(": SUCCESS");
} else {
Serial.print(": ERROR!");
}
}
void tftInit(){
tft.begin();
tft.setRotation(3);
lv_disp_draw_buf_init( &draw_buf, buf, NULL, DISPLAY_BUF_SIZE ); //init draw Buffer
/*Initialize the display*/
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
/*Change the following line to your display resolution*/
disp_drv.hor_res = display_widht;
disp_drv.ver_res = display_height;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
/*Initialize the input device driver*/
static lv_indev_drv_t touch_drv;
lv_indev_drv_init( &touch_drv );
touch_drv.type = LV_INDEV_TYPE_POINTER;
touch_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &touch_drv );
//create simple label
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, "Hello World!!" );
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
}
void setup() {
Serial.begin(115200); /* prepare for possible serial debug */
i2cInit();
touchInit(); //initialize touch
lv_init();
}
void loop() {
touch.loop();
lv_task_handler(); /* let the GUI do its work */
delay(5);
}
these are my main.ino and lv_config.h-files:
https://gist.github.com/kokospalme/a65448c1d10704066b9c6d2350c84a6d
even if I change LV_MEM_SIZE to something small like 1 or 10, I get the error, that " region `dram0_0_seg' overflowed by 22272 bytes". What am I doing wrong?

Related

ESP32-C3-DevKitC-02 Getting Junk Data on UART for AT commands

I am interfacing A7672S 4G module with ESP32-C3-DevKitC-02 over Uart0
The problem i am facing is for any AT command published,i am getting lot of junk data
I have tried publising AT to the same 4G module using arduino ,i am able to get the correct response only with this ESP module i am seeing such issues
void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
// We won't use a buffer for sending data.
uart_driver_install(UART_NUM_0, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
#define RX_BUF_SIZE 1024
int sendData( const char *data)
{
static const char *TX_TASK_TAG = "TX_TASK";
esp_log_level_set(TX_TASK_TAG, ESP_LOG_VERBOSE);
const int len = strlen(data);
const int txBytes = uart_write_bytes(UART_NUM_0, data, len);
ESP_LOGI(TX_TASK_TAG, "Wrote %d bytes", txBytes);
return txBytes;
}
static uint8_t receiveData(uint8_t *data,unsigned int delay_ms)
{
uint8_t rxBytes = 0;
static const char *RX_TASK_TAG = "RX_TASK";
esp_log_level_set(RX_TASK_TAG, ESP_LOG_VERBOSE);
rxBytes = uart_read_bytes(UART_NUM_0, data,RX_BUF_SIZE, delay_ms / portTICK_PERIOD_MS);
data[rxBytes]='\0';
ESP_LOGI(RX_TASK_TAG, "Received %d bytes:\nRxData:%s\n", rxBytes,data);
return rxBytes;
}
uint8_t *data = (uint8_t *)malloc(RX_BUF_SIZE + 1);
uint8_t len=0;
static const char *MAIN_TAG = "MAIN_FUNCTION";
esp_log_level_set(MAIN_TAG, ESP_LOG_VERBOSE);
memset(data, 0, RX_BUF_SIZE + 1);
uart_init();
vTaskDelay(20);
uart_flush(UART_NUM_0);
sendData("AT+CGMI\r\n");
len = receiveData(data,2000);
if(OK == check_response(data,(unsigned char*)"OK"))
{
ESP_LOGI(MAIN_TAG,"Incorporated AT Response Received");
}
else
{
ESP_LOGI(MAIN_TAG,"AT Response Not Received");
}

Electric UI example ESP32 websockets example code issue

This is the example code given for Electric UI's ESP32 websockets intergration.
// This example was written with the ESP8266 and ESP32 as the target hardware.
// Connects to a wifi access point and runs a websockets server as a transport for eUI.
// The ws path is hinted to the UI over the serial connection which ruggedises connection discovery.
// Base wifi libraries from the ESP library pack
#include "WiFi.h"
#include "WiFiMulti.h"
#include "WiFiClientSecure.h"
// Websockets library https://github.com/Links2004/arduinoWebSockets
#include "WebSocketsServer.h"
#include "electricui.h"
#define LED_PIN LED_BUILTIN
// Define default network credentials
char * wifi_ssid = "ssid";
char * wifi_pass = "password";
uint8_t ws_connected = 0; //state indication
uint8_t ws_port = 80;
char ws_path[] = "ws(s)://255.255.255.255:81";
// Simple variables to modify the LED behaviour
uint8_t blink_enable = 1; //if the blinker should be running
uint8_t led_state = 0; //track if the LED is illuminated
uint16_t glow_time = 200; //in milliseconds
// Keep track of when the light turns on or off
uint32_t led_timer = 0;
//example variables
uint8_t example_uint8 = 21;
uint16_t example_uint16 = 321;
uint32_t example_uint32 = 654321;
float example_float = 3.141592;
char demo_string[] = "ESP32 Test Board";
eui_message_t dev_msg_store[] = {
EUI_UINT8( "wsc", ws_connected),
EUI_CHAR_ARRAY( "ws", ws_path ),
EUI_UINT8( "led_blink", blink_enable ),
EUI_UINT8( "led_state", led_state ),
EUI_UINT16( "lit_time", glow_time ),
EUI_UINT8( "ui8", example_uint8 ),
EUI_UINT16( "i16", example_uint16 ),
EUI_UINT32( "i32", example_uint32 ),
EUI_FLOAT( "fPI", example_float ),
EUI_CHAR_ARRAY_RO( "name", demo_string ),
};
WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(ws_port);
void tx_putc(uint8_t *data, uint16_t len);
void ws_tx_putc(uint8_t *data, uint16_t len);
eui_interface_t comm_links[] = {
EUI_INTERFACE(&tx_putc),
EUI_INTERFACE(&ws_tx_putc),
};
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
uint8_t * iter = payload;
uint8_t * end = payload + length;
switch(type)
{
case WStype_DISCONNECTED:
ws_connected = 2;
break;
case WStype_CONNECTED:
ws_connected = 3;
break;
case WStype_TEXT:
// send data to all connected clients
// webSocket.broadcastTXT("message here");
break;
case WStype_BIN:
while( iter < end )
{
eui_parse(*iter++, &comm_links[1]);
}
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
ws_connected = 4;
break;
}
}
void wifi_handle()
{
if( WiFiMulti.run() == WL_CONNECTED )
{
//we have a wifi connection
if(!ws_connected)
{
webSocket.begin();
webSocket.onEvent(webSocketEvent);
ws_connected = 1;
// The hint is formatted like ws://255.255.255.255:81
memset( ws_path, 0, sizeof(ws_path) ); //clear the string first
snprintf(ws_path, sizeof(ws_path), "ws://%s:%d", WiFi.localIP().toString().c_str(), ws_port);
glow_time = 200;
// Using Arduino Strings
// String ws_path_string = "ws://" + WiFi.localIP().toString().c_str() + ":" + String(ws_port);
// ws_path_string.toCharArray(ws_path, sizeof(ws_path));
}
else
{
webSocket.loop();
}
}
else
{
//no connection, try again later
ws_connected = 0;
}
}
void eui_callback( uint8_t message )
{
switch(message)
{
case EUI_CB_TRACKED:
// UI recieved a tracked message ID and has completed processing
break;
case EUI_CB_UNTRACKED:
{
// UI passed in an untracked message ID
// Grab parts of the inbound packet which are are useful
eui_header_t header = comm_links[0].packet.header;
uint8_t *name_rx = comm_links[0].packet.id_in;
void *payload = comm_links[0].packet.data_in;
// See if the inbound packet name matches our intended variable
if( strcmp( (char *)name_rx, "talk" ) == 0 )
{
webSocket.broadcastTXT("hello over websockets");
glow_time = 50;
}
}
break;
case EUI_CB_PARSE_FAIL:
break;
}
}
void setup()
{
Serial.begin(115200);
pinMode( LED_BUILTIN, OUTPUT );
//eUI setup
comm_links[0].interface_cb = &eui_callback;
eui_setup_interfaces(comm_links, 2);
EUI_TRACK(dev_msg_store);
eui_setup_identifier("esp32", 5);
WiFiMulti.addAP(wifi_ssid, wifi_pass);
led_timer = millis();
}
void loop()
{
wifi_handle();
while(Serial.available() > 0)
{
eui_parse(Serial.read(), &comm_links[0]);
}
if( blink_enable )
{
// Check if the LED has been on for the configured duration
if( millis() - led_timer >= glow_time )
{
led_state = !led_state; //invert led state
led_timer = millis();
}
}
digitalWrite( LED_PIN, led_state ); //update the LED to match the intended state
}
void tx_putc( uint8_t *data, uint16_t len )
{
Serial.write( data, len );
}
void ws_tx_putc( uint8_t *data, uint16_t len )
{
webSocket.broadcastBIN( data, len);
}
When I enter my SSID and Password the serial monitor just displays:
E (2462) wifi:Association refused temporarily, comeback time 200 mSec
However the LED is blinking as it should.... The Electric UI shows no devices found....

Inverting a bitmap in Embarcadero C++Builder

The same problem happens in Borland C++Builder 6 and Embarcadero C++Builder 2010.
When I try to invert an image, the form freezes for about 5 seconds and nothing happens. When I click again, the image is inverted within a blink of an eye, and again, again...
To reproduce, create a form with a TImage and two TButton's using this code:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <jpeg.hpp>
#pragma hdrstop
#pragma package(smart_init)
#pragma resource "*.dfm"
#include "Unit1.h"
TForm1 *Form1;
Graphics::TBitmap *CurrentBitmap;
bool bLoaded = false;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
CurrentBitmap = new Graphics::TBitmap;
}
//---------------------------------------------------------------------------
bool __fastcall Invert( TImage *img ) {
if( bLoaded ) {
double Scale, ScaleW, ScaleH;
Graphics::TBitmap *bmp = new Graphics::TBitmap;
bmp->Assign( CurrentBitmap );
DWORD **pixel = new DWORD*[bmp->Height];
for( long y=0; y<bmp->Height; y++ ) {
pixel[y] = (DWORD*)(bmp->ScanLine[y]);
for( long x=0; x<bmp->Width; x++ ) {
if( pixel[y][x] == clBlack ) {
pixel[y][x] = clWhite;
} else if( pixel[y][x] == clWhite ) {
pixel[y][x] = clBlack;
}
}
}
delete[] pixel;
ScaleW = (double)bmp->Width / img->ClientWidth;
ScaleH = (double)bmp->Height / img->ClientHeight;
if( ScaleW > ScaleH ) {
Scale = ScaleW;
} else {
Scale = ScaleH;
}
CurrentBitmap->Assign( bmp );
img->Picture->Bitmap->Canvas->StretchDraw(Rect(0, 0, bmp->Width/Scale, bmp->Height/Scale), bmp );
delete bmp;
return true;
} else {
return false;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) {
TJPEGImage *jpg = new TJPEGImage();
jpg->LoadFromFile( "V:\\CBuilder\\BCB10\\GerberTest\\Testdata\\GerberTest.dpi2400.mskcmp.jpg" );
CurrentBitmap->Width = jpg->Width;
CurrentBitmap->Height = jpg->Height;
CurrentBitmap->Canvas->StretchDraw(Rect(0, 0, jpg->Width, jpg->Height), jpg );
bLoaded = true;
double Scale, ScaleW, ScaleH;
ScaleW = (double)jpg->Width / Image1->ClientWidth;
ScaleH = (double)jpg->Height / Image1->ClientHeight;
if( ScaleW > ScaleH ) {
Scale = ScaleW;
} else {
Scale = ScaleH;
}
Image1->Canvas->StretchDraw(Rect(0, 0, jpg->Width/Scale, jpg->Height/Scale), jpg );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender) {
Invert( Image1 );
}
I cannot explain why the application freezes, or what the code is doing during the 5 second delay.
Like Remy Lebeau mentioned you should set the PixelFormat. I tried your solution which did not seems to invert images properly. Below you find a solution which should work properly.
#include <JPEG.hpp>
Byte __fastcall IntToByte(int AValue)
{
if (AValue > 255)
return 255;
else if (AValue < 0)
return 0;
else
return AValue;
}
// ---------------------------------------------------------------------------
void __fastcall InvertBitmap(Graphics::TBitmap *ABitmap)
{
Byte *p0;
int red, green, blue;
for (int y = 0; y < ABitmap->Height; y++) {
p0 = (Byte*) ABitmap->ScanLine[y];
for (int x = 0; x < ABitmap->Width; x++) {
red = p0[x * 3];
green = p0[x * 3 + 1];
blue = p0[x * 3 + 2];
// invert
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
p0[x * 3] = IntToByte(red);
p0[x * 3 + 1] = IntToByte(green);
p0[x * 3 + 2] = IntToByte(blue);
}
}
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Screen->Cursor = crHourGlass;
TJPEGImage *jpeg = new TJPEGImage();
Graphics::TBitmap *bitmap = new Graphics::TBitmap();
try {
jpeg->LoadFromFile("**YOUR-JPEG-FILE**");
bitmap->SetSize(jpeg->Width, jpeg->Height);
bitmap->Canvas->Draw(0, 0, jpeg);
bitmap->PixelFormat = pf24bit;
InvertBitmap(bitmap);
Image1->Picture->Bitmap->Assign(bitmap);
}
__finally {
jpeg->Free();
bitmap->Free();
}
Screen->Cursor = crDefault;
}
// ---------------------------------------------------------------------------

Whats the purpose of "num" in arduinoWebSockets?

Whats the purpose of num in webSocket.sendTXT(num, "Connected"); or at any other place its used in the code, what function does it serve? Because it doesn't ever get defined as anything anywhere, but it is required to
be passed as a function argument for it to work.
In void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) it's set as a function parameter.
Links2004/arduinoWebSockets Library
/*
* WebSocketServer_LEDcontrol.ino
*
* Created on: 26.11.2015
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Hash.h>
#define LED_RED 15
#define LED_GREEN 12
#define LED_BLUE 13
#define USE_SERIAL Serial
ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer server = ESP8266WebServer(80);
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED: {
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
// send message to client
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
if(payload[0] == '#') {
// we get RGB data
// decode rgb data
uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16);
analogWrite(LED_RED, ((rgb >> 16) & 0xFF));
analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF));
analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF));
}
break;
}
}
void setup() {
//USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
//USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
digitalWrite(LED_RED, 1);
digitalWrite(LED_GREEN, 1);
digitalWrite(LED_BLUE, 1);
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// start webSocket server
webSocket.begin();
webSocket.onEvent(webSocketEvent);
if(MDNS.begin("esp8266")) {
USE_SERIAL.println("MDNS responder started");
}
// handle index
server.on("/", []() {
// send index.html
server.send(200, "text/html", "<html><head><script>var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);connection.onopen = function () { connection.send('Connect ' + new Date()); }; connection.onerror = function (error) { console.log('WebSocket Error ', error);};connection.onmessage = function (e) { console.log('Server: ', e.data);};function sendRGB() { var r = parseInt(document.getElementById('r').value).toString(16); var g = parseInt(document.getElementById('g').value).toString(16); var b = parseInt(document.getElementById('b').value).toString(16); if(r.length < 2) { r = '0' + r; } if(g.length < 2) { g = '0' + g; } if(b.length < 2) { b = '0' + b; } var rgb = '#'+r+g+b; console.log('RGB: ' + rgb); connection.send(rgb); }</script></head><body>LED Control:<br/><br/>R: <input id=\"r\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>G: <input id=\"g\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>B: <input id=\"b\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/></body></html>");
});
server.begin();
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
MDNS.addService("ws", "tcp", 81);
digitalWrite(LED_RED, 0);
digitalWrite(LED_GREEN, 0);
digitalWrite(LED_BLUE, 0);
}
void loop() {
webSocket.loop();
server.handleClient();
}
Looking at the library's source code, it reveals that it's a client id, so you can differentiate between multiple clients, that are connected at the same time.
/*
* send text data to client
* #param num uint8_t client id
* #param payload uint8_t *
* #param length size_t
* #param headerToPayload bool (see sendFrame for more details)
* #return true if ok
*/
bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
return false;
}
if(length == 0) {
length = strlen((const char *) payload);
}
WSclient_t * client = &_clients[num];
if(clientIsConnected(client)) {
return sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
}
return false;
}

xCode 3.2.6. Audio unit programming. IIR filter

My name's Antonio from Italy.
I'm trying to create an Audio Unit using xCode 3.2.6, starting from the example at
this link.
This is my first AU project, and I have no other examples to follow.
My project consists of an IIR notch filter. The algorithm I made works fine (I tested in on Matlab), but the AU doesn't work properly (tested on AU Lab). The .mp3 file sounds filtered, but something like a square wave (I suppose by ear) is overlapped with it.
The frequency of that noise seems to be proportional to the f0 parameter.
Here is the .cpp file code:
// Filtro.cpp
#include "Filtro.h"
#define pi 3.1415926535
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
COMPONENT_ENTRY(Filtro)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::Filtro
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Filtro::Filtro (AudioUnit component) : AUEffectBase (component) {
CreateElements ();
Globals () -> UseIndexedParameters (kNumberOfParameters);
SetParameter (kParameter_Gain, kDefaultValue_Gain);
SetParameter (kParameter_f0, kDefaultValue_f0);
SetParameter (kParameter_Q, kDefaultValue_Q);
// code for setting default values for the audio unit parameters
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::GetParameterInfo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ____Parameters
ComponentResult Filtro::GetParameterInfo (
AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo
) {
ComponentResult result = noErr;
outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
| kAudioUnitParameterFlag_IsReadable;
if (inScope == kAudioUnitScope_Global) {
switch (inParameterID) {
case kParameter_Gain:
AUBase::FillInParameterName (
outParameterInfo,
kParamName_Gain,
false
);
outParameterInfo.unit = kAudioUnitParameterUnit_Decibels;
outParameterInfo.minValue = kMinimumValue_Gain;
outParameterInfo.maxValue = kMaximumValue_Gain;
outParameterInfo.defaultValue = kDefaultValue_Gain;
break;
case kParameter_f0: // 9
AUBase::FillInParameterName (
outParameterInfo,
kParamName_f0,
false
);
outParameterInfo.unit = kAudioUnitParameterUnit_Hertz;
outParameterInfo.minValue = kMinimumValue_f0;
outParameterInfo.maxValue = kMaximumValue_f0;
outParameterInfo.defaultValue = kDefaultValue_f0;
outParameterInfo.flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
break;
case kParameter_Q: // 9
AUBase::FillInParameterName (
outParameterInfo,
kParamName_Q,
false
);
outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
outParameterInfo.minValue = kMinimumValue_Q;
outParameterInfo.maxValue = kMaximumValue_Q;
outParameterInfo.defaultValue = kDefaultValue_Q;
outParameterInfo.flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
break;
default:
result = kAudioUnitErr_InvalidParameter;
break;
}
} else {
result = kAudioUnitErr_InvalidParameter;
}
return result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::GetPropertyInfo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus Filtro::GetPropertyInfo ( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 &outDataSize,
Boolean &outWritable)
{
return AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::GetProperty
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus Filtro::GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void *outData )
{
return AUEffectBase::GetProperty (inID, inScope, inElement, outData);
}
#pragma mark ____FiltroEffectKernel
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::FiltroKernel::FiltroKernel()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Filtro::FiltroKernel::FiltroKernel (AUEffectBase *inAudioUnit) :
AUKernelBase (inAudioUnit), mSamplesProcessed (0), mCurrentScale (0) // 1
{
mSampleFrequency = GetSampleRate ();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::FiltroKernel::Reset()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Filtro::FiltroKernel::Reset() {
mCurrentScale = 0;
mSamplesProcessed = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Filtro::FiltroKernel::Process
void Filtro::FiltroKernel::Process (const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inSamplesToProcess,
UInt32 inNumChannels,
bool &ioSilence
) {
if (!ioSilence) {
const Float32 *sourceP = inSourceP;
Float32 *destP = inDestP, inputSample, outputSample;
Float32 Fs= mSampleFrequency;
int f0;
float w0, alpha, b0, b1, b2, a0, a1, a2;
float gain, dBgain, Q, coeff[5], x[5]={0,0,0,0,0} , out = 0;
dBgain = GetParameter (kParameter_Gain); //Get parameter from interface
if (dBgain < kMinimumValue_Gain) dBgain = kMinimumValue_Gain; //Check the right range
if (dBgain > kMaximumValue_Gain) dBgain = kMaximumValue_Gain;
f0 = GetParameter (kParameter_f0);
if (f0 < kMinimumValue_f0) f0 = kMinimumValue_f0;
if (f0 > kMaximumValue_f0) f0 = kMaximumValue_f0;
Q = GetParameter (kParameter_Q);
if (Q < kMinimumValue_Q) Q = kMinimumValue_Q;
if (Q > kMaximumValue_Q) Q = kMaximumValue_Q;
w0 = 2*pi*f0/Fs;
alpha = sin(w0)*sinh(log(2)/(log(exp(1))*2) * Q * w0/sin(w0));
b0 = 1;
b1 = -2*cos(w0);
b2 = 1;
a0 = 1 + alpha;
a1 = -2*cos(w0);
a2 = 1 - alpha;
coeff[0] = b0/a0;
coeff[1] = b1/a0;
coeff[2] = b2/a0;
coeff[3] = -a1/a0;
coeff[4] = -a2/a0;
//----------------------------------------------------------------------------------------------//
// y(n) = b0/a0 * x(n) + b1/a0 * x(n-1) + b2/a0 * x(n-2) * -a1/a0 * y(n-1) * -a2/a0 * y(n-2) //
//----------------------------------------------------------------------------------------------//
for (int i = inSamplesToProcess; i > 0; --i) {
int index = static_cast<long>(mSamplesProcessed * mCurrentScale) % 512; //?
if ((mNextScale != mCurrentScale) && (index == 0)) { //??
mCurrentScale = mNextScale;
mSamplesProcessed = 0;
}
if ((mSamplesProcessed >= sampleLimit) && (index == 0)) { // ??
mSamplesProcessed = 0;
}
gain = pow(10, dBgain/20);
inputSample = *sourceP;
x[0] = inputSample; //x(n)
x[3] = outputSample; //y(n-1)
for (int h = 0; h < 5; h++) { // Processing output sample
out = out+x[h]*coeff[h];
}
for (int h = 4; h > 0; h--) {
x[h]=x[h-1]; //I/O array shifting
}
outputSample = out * gain;
out = 0;
*destP = outputSample;
sourceP += 1;
destP += 1;
mSamplesProcessed += 1;
}
}
}
And that's the header file:
// Filtro.h
#include "AUEffectBase.h"
#include "AUEffectBase.h"
#include "FiltroVersion.h"
#if AU_DEBUG_DISPATCHER
#include "AUDebugDispatcher.h"
#endif
#ifndef __Filtro_h__
#define __Filtro_h__
#pragma mark ____Filtro Parameter Constants
static CFStringRef kParamName_Gain = CFSTR ("Gain");
static const double kDefaultValue_Gain = 0;
static const double kMinimumValue_Gain = -40;
static const double kMaximumValue_Gain = 0;
static CFStringRef kParamName_f0 = CFSTR ("f0");
static const int kDefaultValue_f0 = 1048;
static const int kMinimumValue_f0 = 50;
static const int kMaximumValue_f0 = 20000;
static CFStringRef kParamName_Q = CFSTR ("Q");
static const double kDefaultValue_Q = 0.1;
static const double kMinimumValue_Q = 0.001;
static const double kMaximumValue_Q = 10;
// parameter identifiers
enum { // Defines constants for identifying the parameters; defines the total number of parameters
kParameter_Gain = 0,
kParameter_f0 = 1,
kParameter_Q = 2,
kNumberOfParameters = 3
};
#pragma mark ____Filtro
class Filtro : public AUEffectBase
{
public:
Filtro(AudioUnit component);
#if AU_DEBUG_DISPATCHER
virtual ~Filtro () { delete mDebugDispatcher; }
#endif
virtual AUKernelBase * NewKernel() { return new FiltroKernel(this); }
virtual OSStatus GetParameterInfo(AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo);
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable );
virtual OSStatus GetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
virtual bool SupportsTail () { return false; } // FIND
/*! #method Version */
virtual OSStatus Version() { return kFiltroVersion; }
// virtual ComponentResult GetPresets (CFArrayRef *outData) const;
// virtual OSStatus NewFactoryPresetSet (const AUPreset &inNewFactoryPreset);
protected:
class FiltroKernel : public AUKernelBase {
public:
FiltroKernel (AUEffectBase *inAudioUnit); // 1
virtual void Process (
const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inFramesToProcess,
UInt32 inNumChannels, // equal to 1
bool &ioSilence
);
virtual void Reset();
private:
Float32 mSampleFrequency;
long mSamplesProcessed;
enum {sampleLimit = (int) 10E6};
float mCurrentScale;
float mNextScale;
};
};
#endif#include "FiltroVersion.h"
#if AU_DEBUG_DISPATCHER
#include "AUDebugDispatcher.h"
#endif
#ifndef __Filtro_h__
#define __Filtro_h__
#pragma mark ____Filtro Parameter Constants
static CFStringRef kParamName_Gain = CFSTR ("Gain");
static const double kDefaultValue_Gain = 0;
static const double kMinimumValue_Gain = -40;
static const double kMaximumValue_Gain = 0;
static CFStringRef kParamName_f0 = CFSTR ("f0");
static const int kDefaultValue_f0 = 1048;
static const int kMinimumValue_f0 = 50;
static const int kMaximumValue_f0 = 20000;
static CFStringRef kParamName_Q = CFSTR ("Q");
static const double kDefaultValue_Q = 0.1;
static const double kMinimumValue_Q = 0.001;
static const double kMaximumValue_Q = 10;
// parameter identifiers
enum { // Defines constants for identifying the parameters; defines the total number of parameters
kParameter_Gain = 0,
kParameter_f0 = 1,
kParameter_Q = 2,
kNumberOfParameters = 3
};
#pragma mark ____Filtro
class Filtro : public AUEffectBase
{
public:
Filtro(AudioUnit component);
#if AU_DEBUG_DISPATCHER
virtual ~Filtro () { delete mDebugDispatcher; }
#endif
virtual AUKernelBase * NewKernel() { return new FiltroKernel(this); }
virtual OSStatus GetParameterInfo(AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo);
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable );
virtual OSStatus GetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
virtual bool SupportsTail () { return false; }
/*! #method Version */
virtual OSStatus Version() { return kFiltroVersion; }
protected:
class FiltroKernel : public AUKernelBase {
public:
FiltroKernel (AUEffectBase *inAudioUnit);
virtual void Process (
const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inFramesToProcess,
UInt32 inNumChannels, // equal to 1
bool &ioSilence
);
virtual void Reset();
private:
Float32 mSampleFrequency;
long mSamplesProcessed;
enum {sampleLimit = (int) 10E6};
float mCurrentScale;
float mNextScale;
};
};
#endif
Thank a lot. I hope my English is not too bad.
Your filter implementation does not look correct to me. Maybe it's fine, but it's hard to follow. For example, it looks like you are shifting your stored x values into your stored y values, and even though you clear that up on the next loop, it's all a bit hard to follow.
You might want to check out how I do it here: http://blog.bjornroche.com/2012/08/basic-audio-eqs.html Much cleaner!
Also, are you processing mono samples or multichannel audio, because your Process function looks like it will only work as you intend with mono audio. (I haven't worked with AU's recently enough to be able to answer this myself from looking at your code)
Problem solved!!! After 3 days, I found the right way to avoid the variables reset every audio frame. I just declared those state variables into the Filtro.h file at the fourth line from the bottom, and than I initialised them into the "AUKernelBase (inAudioUnit)" in Filtro.cpp file. I hope it can be helpful to other people. Bye.

Resources