element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Personal Blogs
  • Community Hub
  • More
Personal Blogs
Legacy Personal Blogs Simple Arduino Music Box: Voices
  • Blog
  • Documents
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: jc2048
  • Date Created: 19 May 2018 12:17 PM Date Created
  • Views 2965 views
  • Likes 10 likes
  • Comments 2 comments
  • musicmakerch
  • ardintermediate
  • arduino_projects
  • uno
  • music
  • arduino uno project
  • arduino
  • music box
Related
Recommended

Simple Arduino Music Box: Voices

jc2048
jc2048
19 May 2018
image

Simple Music Maker

Enter Your Electronics & Design Project for Your Chance to Win a Fog Machine and a $100 Shopping Cart!

Back to The Project14 homepage image

Project14 Home
Monthly Themes
Monthly Theme Poll

 

Introduction

 

This is a continuation of A Simple Arduino Music Box that I did for Project14.

 

The waveform for the note produced is held in a table in the Arduino's memory. That waveform is a description of the wave in the time

domain, ie what you'd see on an oscilloscope. Originally, for simplicity, I made that waveform a sine wave but there's no reason why it

shouldn't be something more complicated.

 

Although there are various methods we could use to describe the way that the shape of a waveform develops over time, a better approach for

sounds is to synthesize the waveform by adding together sine waves of different frequencies. That, then, will be a description in the

frequency domain similar to what you'd see on a spectrum analyser (we'll be doing the reverse of what the spectrum analyser does - the

analyser determines the frequencies that make up the waveform, we'll be starting with the frequencies and putting them back together to

make the waveform). Those frequencies will need to be integer multiples of the fundamental frequency, otherwise the wave won't end at the

same level as it starts and there will be a discontinuity where they join when we put them end to end. Frequencies that have an integer

relationship to a fundamental are called harmonics. (Note that the fundamental is the first harmonic, so the frequency that is twice the

fundamental is the second harmonic, and so on.)

 

The program

 

Here's a program to do that. It's written in C and was compiled with Visual C++ 2010. I imagine any C or C++ compiler going would be able

to do the same. Bear in mind that I'm a hardware enginer, so don't take it as an example of good programming technique - I know that it

isn't, but it does the job and it doesn't need to be at all efficient given the memory resources of a PC and the speed at which the processor

runs.

 

The includes at the start are meant to be:

 

#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <dos.h>

#include <errno.h>

#include <math.h>

 

/****************************************************************/
/* sw-wave-table.c                                              */
/*           Creates waveform by piecing together sine waves.   */
/*           Ends up with 512 values in int array that are      */
/*           ready to paste into Arduino sketch.                */
/*           Output file is called waveTable.txt                */
/*           Created with Visual C++ 2010, but should compile   */
/*           with any c++ compiler.                             */
/*           18th May 2018    Jon Clift                         */
/*--------------------------------------------------------------*/
/* Free to use however you like. No guarantee that it does      */
/* anything useful and no support.                              */
/*--------------------------------------------------------------*/
/* Rev   Date     Comments                                      */
/* 1.0   18/05/18                                               */
/****************************************************************/
#include 
#include 
#include 
#include 
#include 
#include 
// variables
FILE *handle;
FILE *handle2;
char temp_string[256];
unsigned int waveTable[512];
float floatWaveTable[512];
// this defines the waveform
// first value is amplitude of fundamental (normally, just set to 1.0)
// that's followed by amplitudes of harmonics 2 to 10
// no explicit phase information - assumes all start in phase (which is ok for audio)
//float harmonicTable[10] = {1.0,0.0,0.9,0.0,0.8,0.0,0.0,0.0,0.0,0.0};
float harmonicTable[10] = {1.0,0.9,0.8,0.7,0.6,0.5,0.4,0.3,0.0,0.0};
float scaleFactor = 1.0;
float maxValue = 0.0;
// main routine
void main(int argc,char *argv[])
{   int i,j;
    /* print banner */
    printf("\n--- waveTable DOS UTILITY PROGRAM V1.0 ---\n");
    printf("Builds wave table for Arduino Music Box blog.\n");
 /* generate float wave table in array */
 for(i=0;i<512;i++) {
  floatWaveTable[i]= 0.0;
  }
 for(j=0;j<10;j++) {
  for(i=0;i<512;i++) {
   floatWaveTable[i] = floatWaveTable[i] + ((sin(((j+1) * 2.0 * 3.1415926/512.0) * i)) * harmonicTable[j]);
   }
  }
   /* find maximum value and determine scale factor */
   for(i=0;i<512;i++) {
    if(floatWaveTable[i] > maxValue)
     maxValue = floatWaveTable[i];
       }
   scaleFactor = 32767.0 / maxValue;
    /* convert to int wave table in array */
   for(i=0;i<512;i++) {
        waveTable[i] = (unsigned int) ((floatWaveTable[i] * scaleFactor) + 32768);
        }
     /* open output file */
    if((handle=fopen("waveTable.txt","wt"))==NULL) {
        printf("Failed to open output file.\n");
        _fcloseall();
        }
 else {
  /* write file banner */
  fprintf(handle,"//\n");
  fprintf(handle,"//  --- Wave table - generated by waveTable.exe \n");
  fprintf(handle,"//\n");
  fprintf(handle,"unsigned int waveTable[512] = {");
  /* write table to file */
  fprintf(handle,"\n");
  for (i=0;i<32;i++) {
   fprintf(handle,"   ");
   for(j=0;j<16;j++) {
    fprintf(handle,"0x%04x",waveTable[(i*16) + j]);
    if(j<15)
     fprintf(handle,",");
    else {
     if(i==31)
      fprintf(handle,"};\n");
     else
      fprintf(handle,",\n");
     }
    }
   }
 /* close output file */
 fclose(handle);
 
 /* open output .csv file */
    if((handle2=fopen("waveTable.csv","wt"))==NULL) {
        printf("Failed to open .csv output file.\n");
        _fcloseall();
        }
 else {
 
  /* write table to file */
  for (i=0;i<512;i++) {
   fprintf(handle2,"%i,%i,\n",i,waveTable[i]);
   }
  }
  /* close output file */
  fclose(handle2);
  
     printf("Done.\n");
  }
 
}

 

 

The amplitudes of the first 10 harmonics are held in a table. The program constructs the wave table in the form of floating point values

by scanning across the wave table once for each harmonic adding the computed sine values for that harmonic to what is already there. Once

that is done, it finds the largest value in the wave table and then produces an unsigned int table which is appropriately scaled from the

floating point one.

 

The output from the table is a text file that I then paste into the Arduino sketch (an alternative method would have been to output a

header file that could be included in the sketch). I've changed the name of the table to 'waveTable' as that seemed a better description

than 'sineTable', so references to sineTable in the Arduino sketch will need to be changed.

 

The program also outputs a .csv file that can be read into a spreadsheet program and used to view the resulting waveform.

 

A Couple of Examples

 

First example: fundamental and just the 3rd and 5th harmonics. This will be fairly mellow.

 

float harmonicTable[10] = {1.0,0.0,0.9,0.0,0.8,0.0,0.0,0.0,0.0,0.0};

 

That produces this waveform in the table

 

image

 

looks like this at the loudspeaker terminals

 

image

 

and sounds like this

 

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

Second example: fundamental and lots of harmonics, gently tapering off. This will be harsher as a sound.

 

float harmonicTable[10] = {1.0,0.9,0.8,0.7,0.6,0.5,0.4,0.3,0.0,0.0};

 

That produces this waveform

 

image

 

looks like this at the loudspeaker terminals

 

image

 

and sounds like this

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

Something that's surprised me in all this is just what an effect the abrupt transitions at the start and end of the note have on the

quality. They completely wreck the intended sound giving a really objectionable clicking/slapping noise. Definitely need that envelope generator.

 

Next blog: Simple Arduino Music Box: Chords

  • Sign in to reply

Top Comments

  • genebren
    genebren over 7 years ago +1
    Jon, Nice update on your series of blogs on your project. Also, congratulations on your achieving the Tesla level (8). Gene
  • jc2048
    jc2048 over 7 years ago in reply to genebren +1
    Thank you and congratulations on you getting to Tesla, too.
Parents
  • genebren
    genebren over 7 years ago

    Jon,

     

    Nice update on your series of blogs on your project.  Also, congratulations on your achieving the Tesla level (8).

     

    Gene

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • genebren
    genebren over 7 years ago

    Jon,

     

    Nice update on your series of blogs on your project.  Also, congratulations on your achieving the Tesla level (8).

     

    Gene

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • jc2048
    jc2048 over 7 years ago in reply to genebren

    Thank you and congratulations on you getting to Tesla, too.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube