Thursday, November 15, 2012

Auduino With Delay

This is the first in a series of posts introducing simple audio effects that can be used in micro controller projects.

Next Week - Bit Crushing effects

The Delay effect is one of the simplest and most effective enhancements we can add to our audio projects.

The delay effect works by recording the output as it is being generated and then mixing this sound back in with itself - after a delay. The result should be familiar to anyone who has every played an electric guitar through an amp with reverb.

In the case of the Auduino synthesizer the result is a mild echo effect and slightly smoother, more metallic sound - the effect can be turned on or off through a push button in the code provided below.

How do we create the delay effect
Delay is very simple to add in a microcontroller, all we need is a block of memory to record the output in.

The larger the block of memory, the longer the delay we can record and the deeper the effect.

In this case we are using a 1K block of memory in the array named sDelayBuffer -

// Duane B
// rcarduino.blogspot.com
// 15/11/2012
// Very simple ring buffer delay
// we record the output in this array
// and then mix it back in with the output as the buffer wraps around
// can be switched on and off by a button on DELAY_BUTTON
#define MAX_DELAY 1024
unsigned char sDelayBuffer[MAX_DELAY];
unsigned int nDelayCounter = 0;
unsigned char bDelay;

The other modification is inside the interrupt service routine which generates the Audiuno output, essentially what we are doing is adding the sound we recorded 1/8th of a second ago on top of the current output value -


  // Duane B
  // rcarduino.blogspot.com
  // 15/11/2012
  // add a button to set bDelay true or false to turn delay on and off
  if(bDelay)
  {
    // Output to PWM (this is faster than using analogWrite) 
    // Here we add the delay buffer to the output value, this produces
    // an subtle echo effect, the delay buffer is effectivley replaying the sound from
    // 1/8th of a second ago.
 
    LED_PORT |= 1 << LED_BIT; // Faster than using digitalWrite
    PWM_VALUE = (output + (sDelayBuffer[nDelayCounter]))>>1;
   
    // add the new output to the buffer so we can use it when the buffer next wraps around
    sDelayBuffer[nDelayCounter] = PWM_VALUE;
    nDelayCounter++;
    if(nDelayCounter == MAX_DELAY)
    {
      nDelayCounter = 0;
    }
  }
  else
  {
    LED_PORT &= ~(1 << LED_BIT); // Faster than using digitalWrite
   
    PWM_VALUE = output;
  }

We test whether delay is enabled, if it is we calculate the output value by adding the initial output to the earlier recorded output from our delay buffer. After outputting this combined value we record it in the delay buffer replacing the value we just used. Over time, the code cycles through the delay buffer over and over again, mixing the current output with a sample from 1/8th of a second back - a bit like playing your instrument in a large hall where the distinct sound is the result of the current sound being constantly mixed with its echo.

Thats all there is to generating delay in a micro controller synth engine - exactly the same code is used to create the delay effect in the RCArduino Five Dollar Synthesizer.


The RCArduino Five Dollar Synthesizer is another audio project enhanced with this delay effect -

http://rcarduino.blogspot.com/2012/10/five-dollar-synthesiser.html 


Further Development
The amount of delay we can provide is determined to the memory we use to record the samples. In the Auduino we are using 1K which at an 8K play back rate gives us 125ms of delay. This can be increased by bit crushing the samples - using 4 bits per sample we get 250ms, 2 bits gets us half a second, with 1 bit we can get a whole second. Unfortunately initial experiments suggest that the effect is largely lost when applying these techniques, its a bit like shouting into a cave and getting a different echo back - your ears just don't buy it.

Auduino Accreditation
The Auduino is an original work by Peter Knight, the original project can be found here -
http://code.google.com/p/tinkerit/wiki/Auduino

Auduino with delay

Auduino with delay is a very slight modification by Duane B (rcarduino) to the original work of Peter Knight.

Notes
- This code also include the volatile fix which allows the Auduino to work correctly in Arduino 1.0 and later
- Remember to use a pull up or pull down resistor if you are not using a push button or switch for the delay button or if your more comfortable modifying the code, replace the button code with true or false.
- LED 13, now indicates whether delay is on or off.


// Auduino, the Lo-Fi granular synthesiser
//
// by Peter Knight, Tinker.it http://tinker.it
//
// Help:      http://code.google.com/p/tinkerit/wiki/Auduino
// More help: http://groups.google.com/group/auduino
//
// Analog in 0: Grain 1 pitch
// Analog in 1: Grain 2 decay
// Analog in 2: Grain 1 decay
// Analog in 3: Grain 2 pitch
// Analog in 4: Grain repetition frequency
//
// Digital 3: Audio out (Digital 11 on ATmega8)
//
// Changelog:
// 19 Nov 2008: Added support for ATmega8 boards
// 21 Mar 2009: Added support for ATmega328 boards
// 7 Apr 2009: Fixed interrupt vector for ATmega328 boards
// 8 Apr 2009: Added support for ATmega1280 boards (Arduino Mega)

#include <avr/io.h>
#include <avr/interrupt.h>

uint16_t syncPhaseAcc;
volatile uint16_t syncPhaseInc;
uint16_t grainPhaseAcc;
volatile uint16_t grainPhaseInc;
uint16_t grainAmp;
volatile uint8_t grainDecay;
uint16_t grain2PhaseAcc;
volatile uint16_t grain2PhaseInc;
uint16_t grain2Amp;
volatile uint8_t grain2Decay;

// Map Analogue channels
#define SYNC_CONTROL         (4)
#define GRAIN_FREQ_CONTROL   (0)
#define GRAIN_DECAY_CONTROL  (2)
#define GRAIN2_FREQ_CONTROL  (3)
#define GRAIN2_DECAY_CONTROL (1)

// DB
#define SMOOTH_PIN 8


// Changing these will also requires rewriting audioOn()

#if defined(__AVR_ATmega8__)
//
// On old ATmega8 boards.
//    Output is on pin 11
//
#define LED_PIN       13
#define LED_PORT      PORTB
#define LED_BIT       5
#define PWM_PIN       11
#define PWM_VALUE     OCR2
#define PWM_INTERRUPT TIMER2_OVF_vect



#elif defined(__AVR_ATmega1280__)
//
// On the Arduino Mega
//    Output is on pin 3
//
#define LED_PIN       13
#define LED_PORT      PORTB
#define LED_BIT       7
#define PWM_PIN       3
#define PWM_VALUE     OCR3C
#define PWM_INTERRUPT TIMER3_OVF_vect
#else
//
// For modern ATmega168 and ATmega328 boards
//    Output is on pin 3
//
#define PWM_PIN       3
#define PWM_VALUE     OCR2B
#define LED_PIN       13
#define LED_PORT      PORTB
#define LED_BIT       5
#define PWM_INTERRUPT TIMER2_OVF_vect
#endif

// Duane B
// rcarduino.blogspot.com
// 15/11/2012
// Very simple ring buffer delay
// we record the output in this array
// and then mix it back in with the output as the buffer wraps around
// can be switched on and off by a button on DELAY_BUTTON
#define MAX_DELAY 1024
unsigned char sDelayBuffer[MAX_DELAY];
unsigned int nDelayCounter = 0;
unsigned char bDelay;

#define DELAY_BUTTON 4


// Smooth logarithmic mapping
//
uint16_t antilogTable[] = {
  64830,64132,63441,62757,62081,61413,60751,60097,59449,58809,58176,57549,56929,56316,55709,55109,
  54515,53928,53347,52773,52204,51642,51085,50535,49991,49452,48920,48393,47871,47356,46846,46341,
  45842,45348,44859,44376,43898,43425,42958,42495,42037,41584,41136,40693,40255,39821,39392,38968,
  38548,38133,37722,37316,36914,36516,36123,35734,35349,34968,34591,34219,33850,33486,33125,32768
};
uint16_t mapPhaseInc(uint16_t input) {
  return (antilogTable[input & 0x3f]) >> (input >> 6);
}

// Stepped chromatic mapping
//
uint16_t midiTable[] = {
  17,18,19,20,22,23,24,26,27,29,31,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,
  77,82,86,92,97,103,109,115,122,129,137,145,154,163,173,183,194,206,218,231,
  244,259,274,291,308,326,346,366,388,411,435,461,489,518,549,581,616,652,691,
  732,776,822,871,923,978,1036,1097,1163,1232,1305,1383,1465,1552,1644,1742,
  1845,1955,2071,2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143,
  4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286,8779,9301,9854,
  10440,11060,11718,12415,13153,13935,14764,15642,16572,17557,18601,19708,20879,
  22121,23436,24830,26306
};
uint16_t mapMidi(uint16_t input) {
  return (midiTable[(1023-input) >> 3]);
}

// Stepped Pentatonic mapping
//
uint16_t pentatonicTable[54] = {
  0,19,22,26,29,32,38,43,51,58,65,77,86,103,115,129,154,173,206,231,259,308,346,
  411,461,518,616,691,822,923,1036,1232,1383,1644,1845,2071,2463,2765,3288,
  3691,4143,4927,5530,6577,7382,8286,9854,11060,13153,14764,16572,19708,22121,26306
};

uint16_t mapPentatonic(uint16_t input) {
  uint8_t value = (1023-input) / (1024/53);
  return (pentatonicTable[value]);
}


void audioOn() {
#if defined(__AVR_ATmega8__)
  // ATmega8 has different registers
  TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
  TIMSK = _BV(TOIE2);
#elif defined(__AVR_ATmega1280__)
  TCCR3A = _BV(COM3C1) | _BV(WGM30);
  TCCR3B = _BV(CS30);
  TIMSK3 = _BV(TOIE3);
#else
  // Set up PWM to 31.25kHz, phase accurate
  TCCR2A = _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(CS20);
  TIMSK2 = _BV(TOIE2);
#endif
}


void setup() {
  pinMode(PWM_PIN,OUTPUT);
  audioOn();
  pinMode(LED_PIN,OUTPUT);

  pinMode(DELAY_BUTTON,INPUT);
 
  // set pin mode and turn on pull up so that default mode
  // is PENTATONIC, pull the pin low to switch to smooth
  pinMode(SMOOTH_PIN,INPUT);
  digitalWrite(SMOOTH_PIN,HIGH);
}

void loop() {
  // The loop is pretty simple - it just updates the parameters for the oscillators.
  //
  // Avoid using any functions that make extensive use of interrupts, or turn interrupts off.
  // They will cause clicks and poops in the audio.
 
  // defaults to pentatonic stepped tones, pull pin low for smooth frequency without distinct tones
  //    syncPhaseInc = mapPhaseInc(analogRead(SYNC_CONTROL)) / 4;

  syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));
 
  // updated 29/01/2013
  // pull the DELAY_BUTTON pin high for delay, low for no delay
  // use either a pull up/pull down resistor
  // or a pull up resistor with a toggle switch between the pin and ground
  bDelay = digitalRead(DELAY_BUTTON);
 
  // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
  //syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));
 
  // Stepped pentatonic mapping: D, E, G, A, B
 

  grainPhaseInc  = mapPhaseInc(analogRead(GRAIN_FREQ_CONTROL)) / 2;
  grainDecay     = analogRead(GRAIN_DECAY_CONTROL) / 8;
  grain2PhaseInc = mapPhaseInc(analogRead(GRAIN2_FREQ_CONTROL)) / 2;
  grain2Decay    = analogRead(GRAIN2_DECAY_CONTROL) / 4;
}


SIGNAL(PWM_INTERRUPT)
{
  uint8_t value;
  uint16_t output;

  syncPhaseAcc += syncPhaseInc;
  if (syncPhaseAcc < syncPhaseInc) {
    // Time to start the next grain
    grainPhaseAcc = 0;
    grainAmp = 0x7fff;
    grain2PhaseAcc = 0;
    grain2Amp = 0x7fff;
//    LED_PORT ^= 1 << LED_BIT; // Faster than using digitalWrite
  }
 
  // Increment the phase of the grain oscillators
  grainPhaseAcc += grainPhaseInc;
  grain2PhaseAcc += grain2PhaseInc;

  // Convert phase into a triangle wave
  value = (grainPhaseAcc >> 7) & 0xff;
  if (grainPhaseAcc & 0x8000) value = ~value;
  // Multiply by current grain amplitude to get sample
  output = value * (grainAmp >> 8);

  // Repeat for second grain
  value = (grain2PhaseAcc >> 7) & 0xff;
  if (grain2PhaseAcc & 0x8000) value = ~value;
  output += value * (grain2Amp >> 8);

  // Make the grain amplitudes decay by a factor every sample (exponential decay)
  grainAmp -= (grainAmp >> 8) * grainDecay;
  grain2Amp -= (grain2Amp >> 8) * grain2Decay;

  // Scale output to the available range, clipping if necessary
  output >>= 9;
  if (output > 255) output = 255;

  // Duane B
  // rcarduino.blogspot.com
  // 15/11/2012
  // add a button to set bDelay true or false to turn delay on and off
  if(bDelay)
  {
    // Output to PWM (this is faster than using analogWrite) 
    // Here we add the delay buffer to the output value, this produces
    // an subtle echo effect, the delay buffer is effectivley replaying the sound from
    // 1/8th of a second ago.
 
    LED_PORT |= 1 << LED_BIT; // Faster than using digitalWrite
    PWM_VALUE = (output + (sDelayBuffer[nDelayCounter]))>>1;
   
    // add the new output to the buffer so we can use it when the buffer next wraps around
    sDelayBuffer[nDelayCounter] = PWM_VALUE;
    nDelayCounter++;
    if(nDelayCounter == MAX_DELAY)
    {
      nDelayCounter = 0;
    }
  }
  else
  {
    LED_PORT &= ~(1 << LED_BIT); // Faster than using digitalWrite
   
    PWM_VALUE = output;
  }
}


44 comments:

  1. This is gonna sound silly, but how should the button for the delay be wired?

    Thank you so much for updating this code!

    ReplyDelete
    Replies
    1. LEGIT FULLZ & TOOLS STORE

      Hello to All !

      We are offering all types of tools & Fullz on discounted price.
      If you are in search of anything regarding fullz, tools, tutorials, Hack Pack, etc
      Feel Free to contact

      ***CONTACT 24/7***
      **Telegram > @leadsupplier
      **ICQ > 752822040
      **Skype > Peeterhacks
      **Wicker me > peeterhacks

      "SSN LEADS/FULLZ AVAILABLE"
      "TOOLS & TUTORIALS AVAILABLE FOR HACKING, SPAMMING,
      CARDING, CASHOUT, CLONING, SCRIPTING ETC"

      **************************************
      "Fresh Spammed SSN Fullz info included"
      >>SSN FULLZ with complete info
      >>CC With CVV (vbv & non vbv) Fullz USA
      >>FULLZ FOR SBA, PUA & TAX RETURN FILLING
      >>USA I.D Photos Front & Back
      >>High Credit Score fullz (700+ Scores)
      >>DL number, Employee Details, Bank Details Included
      >>Complete Premium Info with Relative Info

      ***************************************
      COMPLETE GUIDE FOR TUTORIALS & TOOLS

      "SPAMMING" "HACKING" "CARDING" "CASH OUT"
      "KALI LINUX" "BLOCKCHAIN BLUE PRINTS" "SCRIPTING"
      "FRAUD BIBLE"

      "TOOLS & TUTORIALS LIST"
      =>Ethical Hacking Ebooks, Tools & Tutorials
      =>Bitcoin Hacking
      =>Kali Linux
      =>Fraud Bible
      =>RAT
      =>Keylogger & Keystroke Logger
      =>Whatsapp Hacking & Hacked Version of Whatsapp
      =>Facebook & Google Hacking
      =>Bitcoin Flasher
      =>SQL Injector
      =>Premium Logs (PayPal/Amazon/Coinbase/Netflix/FedEx/Banks)
      =>Bitcoin Cracker
      =>SMTP Linux Root
      =>Shell Scripting
      =>DUMPS with pins track 1 and 2 with & without pin
      =>SMTP's, Safe Socks, Rdp's brute
      =>PHP mailer
      =>SMS Sender & Email Blaster
      =>Cpanel
      =>Server I.P's & Proxies
      =>Viruses & VPN's
      =>HQ Email Combo (Gmail, Yahoo, Hotmail, MSN, AOL, etc.)

      *Serious buyers will always welcome
      *Price will be reduce in bulk order
      *Discount offers will gives to serious buyers
      *Hope we do a great business together

      ===>Contact 24/7<===
      ==>Telegram > @leadsupplier
      ==>ICQ > 752822040
      ==>Skype > Peeterhacks
      ==>Wicker me > peeterhacks

      Delete
  2. Like this - http://arduino.cc/en/Tutorial/Button but connected to digital pin 4

    Duane B

    ReplyDelete
  3. Hi Duane, I've built my Auduino in a breadboard with a china made Arduino Duemilanove (Not official that is), could that be the reason it doesn't work? Wiring is OK, but only the first potentiometer seems to work. Wiring is not the problem, as if I switch cables on the breadboard strange noises happen :)

    Regards,

    Pancho

    ReplyDelete
  4. Hi,
    If only one pot seems to work, this is usually because the 'volatile' fix is not being used in the code.

    Are you using the exact code above or the code from the original tinkerkit link, the tinkerkit code has the bug and does not look as if anyone is every going to update it, the code above has the fix.

    Duane B

    ReplyDelete
  5. Hi Duane,

    im just wondering what the smooth pin 8 is for is something supposed to be connected to that pin?

    thanks

    ReplyDelete
  6. Hi,
    At one point it was possible to choose which scale the Auduino would use by changing this line based on user input - syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL)); however having tried many different scales and smooth transitions without scales - this option gives the best results. You can try adding other scales by adding a new map function, the chromatic scale is still in the code so an easy place to start. Also check the blog in a few days, I have finished a really nice resonant low pass filter for Arduino audio projects that I will write up and post over the next few days. Duane.

    ReplyDelete
  7. Hi Duane
    I am trying to upload this code to arduino Micro. But there is problem - TCCR2A was not declared as scope - and higlighted part of the code is TCCR2A = _BV(COM2B1) | _BV(WGM20);. Do you have any solutions or maybe code for arduino micro.

    pls REPLAY
    thanks

    ReplyDelete
    Replies
    1. Try TCCR2 without the A for the Micro.

      Duane B

      Delete
    2. Update, try this as well, change the audioOn function from this -

      void audioOn() {
      #if defined(__AVR_ATmega8__)
      // ATmega8 has different registers
      TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
      TIMSK = _BV(TOIE2);
      #elif defined(__AVR_ATmega1280__)
      TCCR3A = _BV(COM3C1) | _BV(WGM30);
      TCCR3B = _BV(CS30);
      TIMSK3 = _BV(TOIE3);
      #else
      // Set up PWM to 31.25kHz, phase accurate
      TCCR2A = _BV(COM2B1) | _BV(WGM20);
      TCCR2B = _BV(CS20);
      TIMSK2 = _BV(TOIE2);
      #endif
      }

      to this -

      void audioOn() {
      TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
      TIMSK = _BV(TOIE2);
      }

      Duane B

      Delete
    3. still same problem...

      error copy:

      auduino_v5.ino: In function 'void audioOn()':
      auduino_v5:147: error: 'TCCR2' was not declared in this scope
      auduino_v5:147: error: 'WGM20' was not declared in this scope
      auduino_v5:147: error: 'COM21' was not declared in this scope
      auduino_v5:147: error: 'CS20' was not declared in this scope
      auduino_v5:148: error: 'TIMSK' was not declared in this scope
      auduino_v5.ino: In function 'void TIMER2_OVF_vect()':
      auduino_v5:245: error: 'OCR2B' was not declared in this scope
      auduino_v5:259: error: 'OCR2B' was not declared in this scope

      Delete
  8. The micro uses a different chip, an ATMega32u4, its very similar to the ATMega328 in the Arduino UNO however if your accessing the chip registers directly some of them are named differently. To convert the timer counter registers from ATMega328 to ATMega32u4, refer to page 89 onwards of the datasheet here - http://www.atmel.com/Images/doc7766.pdf

    Duane B

    ReplyDelete
  9. hi i'm new at this, wich libraries should i download? or they come with the arduino software by default?

    ReplyDelete
  10. Hi DuaneB I was wondering how is your code licensed to the public, as gnu licensed or what else?

    ReplyDelete

  11. I found this is an informative blog and also very useful and knowledgeable. I would like to thank you for the efforts you have made in writing this blog


    buy modalert online

    buy artvigil online
    buy waklert online
    buy modvigil online

    buy vilafinil online


    ReplyDelete
  12. LEGIT FULLZ & TOOLS STORE

    Hello to All !

    We are offering all types of tools & Fullz on discounted price.
    If you are in search of anything regarding fullz, tools, tutorials, Hack Pack, etc
    Feel Free to contact

    ***CONTACT 24/7***
    **Telegram > @leadsupplier
    **ICQ > 752822040
    **Skype > Peeterhacks
    **Wicker me > peeterhacks

    "SSN LEADS/FULLZ AVAILABLE"
    "TOOLS & TUTORIALS AVAILABLE FOR HACKING, SPAMMING,
    CARDING, CASHOUT, CLONING, SCRIPTING ETC"

    **************************************
    "Fresh Spammed SSN Fullz info included"
    >>SSN FULLZ with complete info
    >>CC With CVV (vbv & non vbv) Fullz USA
    >>FULLZ FOR SBA, PUA & TAX RETURN FILLING
    >>USA I.D Photos Front & Back
    >>High Credit Score fullz (700+ Scores)
    >>DL number, Employee Details, Bank Details Included
    >>Complete Premium Info with Relative Info

    ***************************************
    COMPLETE GUIDE FOR TUTORIALS & TOOLS

    "SPAMMING" "HACKING" "CARDING" "CASH OUT"
    "KALI LINUX" "BLOCKCHAIN BLUE PRINTS" "SCRIPTING"
    "FRAUD BIBLE"

    "TOOLS & TUTORIALS LIST"
    =>Ethical Hacking Ebooks, Tools & Tutorials
    =>Bitcoin Hacking
    =>Kali Linux
    =>Fraud Bible
    =>RAT
    =>Keylogger & Keystroke Logger
    =>Whatsapp Hacking & Hacked Version of Whatsapp
    =>Facebook & Google Hacking
    =>Bitcoin Flasher
    =>SQL Injector
    =>Premium Logs (PayPal/Amazon/Coinbase/Netflix/FedEx/Banks)
    =>Bitcoin Cracker
    =>SMTP Linux Root
    =>Shell Scripting
    =>DUMPS with pins track 1 and 2 with & without pin
    =>SMTP's, Safe Socks, Rdp's brute
    =>PHP mailer
    =>SMS Sender & Email Blaster
    =>Cpanel
    =>Server I.P's & Proxies
    =>Viruses & VPN's
    =>HQ Email Combo (Gmail, Yahoo, Hotmail, MSN, AOL, etc.)

    *Serious buyers will always welcome
    *Price will be reduce in bulk order
    *Discount offers will gives to serious buyers
    *Hope we do a great business together

    ===>Contact 24/7<===
    ==>Telegram > @leadsupplier
    ==>ICQ > 752822040
    ==>Skype > Peeterhacks
    ==>Wicker me > peeterhacks

    ReplyDelete
  13. The increasing popularity of ready-to-drink products is also increasing the demand for coffee concentrates in the market. The high paced lifestyles of consumers are shifting the choice of people from traditional coffee to the concentrated form. Additionally, the use of instant coffee in homes and offices is likely to create opportunities for the coffee concentrate market.


    Also Read: acquired disease testing market, Latin America Generic Injectables Market.

    ReplyDelete
  14. Good day everyone, San Wilson here! If you are wondering how many pages is 1000 words, contact me any time and I will provide you with full guidance.

    ReplyDelete
  15. Hi Everyone! My name is Michael and I am an experienced author working at an independent tech-support firm

    ReplyDelete
  16. allbet casino online gambling service provider that meets international standards and meets all gambler needs.

    ReplyDelete
  17. naza8k We are number 1 in total entertainment.

    ReplyDelete
  18. Oh my goodness, this is so exciting! I absolutely have to investigate further!

    ReplyDelete
  19. CMOLDS leads as the premier mobile app development company uae, offering cutting-edge solutions tailored to your business needs. Elevate your digital presence with our expert team crafting innovative mobile experiences.

    ReplyDelete
  20. Python training develops professional coding skills.It emphasizes practical assignments.This Python training supports career advancement.It is reliable.

    ReplyDelete
  21. Master UI/UX design skills to create intuitive, visually appealing interfaces with real-world project experience.learn ui ux

    ReplyDelete
  22. iOS developer training focuses on professional application development skills for Apple platforms. It explains real-world implementation methods. This ios developer training strengthens programming expertise. Learners develop scalable applications. App architecture is included. Testing procedures are covered. Hands-on practice is provided. It prepares job-ready developers.

    ReplyDelete
  23. Salesforce admin course online delivers flexible learning on platform setup and reporting tools. It explains dashboard creation and customization clearly. This salesforce admin course online strengthens practical CRM knowledge. Learners work on implementation projects. Case studies are included. Expert mentorship is provided. It prepares career-focused administrators.

    ReplyDelete
  24. Nice write-up! ServiceNow online training is a convenient way to gain practical platform skills, learn ITSM best practices, and prepare for real-world ServiceNow administration roles.servicenow online training

    ReplyDelete
  25. Great post! Our devops full course
    builds real-world skills in CI/CD, automation, and cloud deployment.

    ReplyDelete
  26. Great article! I was searching for the best Mulesoft developer course to understand API development and integration concepts. This information is very helpful for beginners who want to build strong MuleSoft development skills.mulesoft developer course

    ReplyDelete
  27. Great article and very informative. Many professionals are enrolling in a Salesforce CPQ course to learn advanced sales automation and quoting processes. A well-structured Salesforce CPQ course provides hands-on experience with configuration, pricing rules, and quote generation in Salesforce.salesforce cpq course

    ReplyDelete
  28. Great article! OnlineITGuru’s servicenow training classes are very helpful for beginners and professionals who want to improve their ServiceNow expertise.servicenow training classes

    ReplyDelete
  29. If you want hands-on experience in API development and management, the Mulesoft API Training by OnlineITGuru provides comprehensive modules covering RAML, API design, and deployment. It’s ideal for professionals seeking practical skills in creating scalable and secure APIs for modern businessesmulesoft api training

    ReplyDelete
  30. For professionals in India looking to boost their integration skills, MuleSoft Training India from OnlineITGuru offers expert-led sessions, practical projects, and certification guidance. It’s a great way to enhance your career in cloud integration and enterprise application developmentMuleSoft Training India

    ReplyDelete
  31. Salesforce CPQ is one of the most valuable skills in today’s CRM job market. Organizations worldwide are searching for skilled professionals who can design and implement efficient sales automation systemslearn salesforce cpq

    ReplyDelete
  32. Thanks for sharing such useful information about enterprise platforms. Many IT professionals are now upgrading their skills with Servicenow Training to understand workflow automation, platform configuration, and IT service management processes. OnlineITGuru offers structured learning with practical examples.servicenow training

    ReplyDelete
  33. Very informative article! Many IT professionals are now exploring the Servicenow Administrator Course to improve their skills in ITSM and automation. Training programs offered by OnlineITGuru include practical labs and real-world scenarios that make it easier to understand ServiceNow administration concepts.servicenow administrator course

    ReplyDelete
  34. Thanks for sharing this useful information about sales automation platforms. A Salesforce CPQ Course helps professionals understand product configuration, pricing strategies, and quote generation within Salesforce. OnlineITGuru offers structured training programs that include practical exercises and real-world use cases.salesforce cpq course

    ReplyDelete
  35. Integration skills are becoming very important in modern IT environments. I recently came across Mulesoft Training programs from OnlineITGuru that focus on API-led connectivity, real-time projects, and practical learning. It’s a good option for developers who want to work with enterprise integration platforms.mulesoft training

    ReplyDelete
  36. Our MuleSoft Developer Training focuses on building REST and SOAP APIs, data transformation with DataWeave, and designing scalable integration solutions. Practical exercises ensure hands-on experience.mulesoft developer training

    ReplyDelete
  37. "This article on ITSM concepts was very insightful! The Servicenow Administrator Course offered by OnlineITGuru covers platform configuration, workflow automation, and ITSM modules, perfect for career advancement.servicenow administrator course

    ReplyDelete
  38. Nice blog post. Mulesoft certification training helps developers prepare for certification exams while gaining practical API development skills.mulesoft certification training

    ReplyDelete
  39. Excellent information shared here. ServiceNow Admin Training is essential for IT professionals who want to build strong skills in ServiceNow platform administration.servicenow admin training

    ReplyDelete