forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

DTMF code sample

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
Art



Joined: 09 Nov 2005
Posts: 647

PostPosted: Sun Feb 03, 2008 1:14 pm    Post subject: DTMF code sample Reply with quote

Here's a DTMF code sample I based on Shine's Polyphonic wave sample.
It makes the correct frequencies, but still doesn't dial numbers on a phone.
The sound is a little different to listen to.. tinny like a car horn, yet in tune.

If you play high quality recorded DTMF sounds the phone DOES dial,
anyone can do that with chunky code that stores the samples.
There must be still some problem with this code.
If anyone sorts it out I'd appreciate the solution.

Code:


#include <pspkernel.h>
#include <pspdebug.h>
#include <pspaudiolib.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <pspctrl.h>

PSP_MODULE_INFO("DTMF", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

#define printf   pspDebugScreenPrintf

int ix;         // counter
int done;      // exit flag

void dump_threadstatus(void);

int exit_callback(int arg1, int arg2, void *common) {
   done = 1;
   sceKernelExitGame();
   return 0;
}

int CallbackThread(SceSize args, void *argp) {
   int cbid;
   cbid = sceKernelCreateCallback("Exit Callback", (void *) exit_callback, NULL);
   sceKernelRegisterExitCallback(cbid);
   sceKernelSleepThreadCB();
   return 0;
}


int SetupCallbacks(void) {
   int thid = 0;
   thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
   if(thid >= 0){sceKernelStartThread(thid, 0, 0);}
   return thid;
}

int  pspAudioInit();
void pspAudioEndPre();
void pspAudioEnd();

#define SAMPLE_COUNT 0x10000
float sample[SAMPLE_COUNT];

#define SAMPLE_RATE 44100
#define OCTAVE_COUNT 6
#define NOTE_END -2
#define NOTE_PAUSE -1

float octaves[OCTAVE_COUNT][12];

typedef struct {
   int note;
   int octave;
   int duration;
} Note_t;

typedef struct {
   Note_t currentNote;
   int noteIndex;
   int currentTime;
   float currentsampleIndex;
   float currentsampleIncrement;
} ChannelState_t;

ChannelState_t channelStates[3];


#define EIGHT_NOTE(note, octave, duration) { note, octave, SAMPLE_RATE * duration / 8}

Note_t channel0[] = {
   EIGHT_NOTE(3, 0, 4),
   EIGHT_NOTE(0, 0, 4),
   EIGHT_NOTE(0, 0, 4),
   EIGHT_NOTE(0, 0, 4),
   EIGHT_NOTE(1, 0, 4),
   EIGHT_NOTE(1, 0, 4),
   EIGHT_NOTE(1, 0, 4),
   EIGHT_NOTE(2, 0, 4),
   EIGHT_NOTE(2, 0, 4),
   EIGHT_NOTE(2, 0, 4),
   EIGHT_NOTE(3, 0, 4),
   EIGHT_NOTE(3, 0, 4),
   EIGHT_NOTE(-1, 0, 4),
   { NOTE_END, 0, 0 }
};

Note_t channel1[] = {
   EIGHT_NOTE(5, 0, 4),
   EIGHT_NOTE(4, 0, 4),
   EIGHT_NOTE(5, 0, 4),
   EIGHT_NOTE(6, 0, 4),
   EIGHT_NOTE(4, 0, 4),
   EIGHT_NOTE(5, 0, 4),
   EIGHT_NOTE(6, 0, 4),
   EIGHT_NOTE(4, 0, 4),
   EIGHT_NOTE(5, 0, 4),
   EIGHT_NOTE(6, 0, 4),
   EIGHT_NOTE(4, 0, 4),
   EIGHT_NOTE(6, 0, 4),
   EIGHT_NOTE(-1, 0, 4),
   { NOTE_END, 0, 0 }
};

Note_t* channels[] = { channel0, channel1 };

void nextNote(int channel)
{
   ChannelState_t* state = &channelStates[channel];
   state->currentNote = channels[channel][state->noteIndex];
   state->currentTime = 0;
   state->currentsampleIndex = 0;
   int note = state->currentNote.note;
   if (note == NOTE_PAUSE) {
      state->currentsampleIncrement = 0;
   } else {
      state->currentsampleIncrement = octaves[state->currentNote.octave][note] * ((float) SAMPLE_COUNT) / ((float) SAMPLE_RATE);
   }

   state->noteIndex++;
   if (channels[channel][state->noteIndex].note == NOTE_END) state->noteIndex = 0;
}

// calculate current value of attack/delay/sustain/release envelope
float adsr(float time, float duration) {
   if (time < 0.0) return 0.0;

   const float attack = 0.0;
   const float decay = 0.0;
   const float sustain = 0.5;
   const float release = 0.0;

   if (time < attack) return time / attack;
   if (time < decay) return (decay - time) / decay * (1.0 - sustain) + sustain;
   if (time < duration) return sustain;
   time -= duration;
   if (time < release) return (release - time) / release * sustain;
   return 0.0;
}

void audioOutCallback(int channel, unsigned short* buf, unsigned int reqn)
{
   ChannelState_t* state = &channelStates[channel];
   unsigned int i;
   for (i = 0; i < reqn; i++) {
      float time = ((float) state->currentTime) / ((float) SAMPLE_RATE);
      if (state->currentTime++ == state->currentNote.duration);

      float value;
      if (state->currentsampleIncrement == 0.0) {
         value = 0.0;
      } else {
         value = sample[(int)state->currentsampleIndex] * adsr(time, ((float) state->currentNote.duration) / ((float) SAMPLE_RATE));
         value *= (float) 0x7000;
         state->currentsampleIndex += state->currentsampleIncrement;
         if (state->currentsampleIndex >= SAMPLE_COUNT) state->currentsampleIndex -= (float) SAMPLE_COUNT;
      }
      buf[0] = value;
      buf[1] = value;
      buf += 2;
   }
}

void audioOutCallback0(void *buf, unsigned int reqn, void *userdata) { audioOutCallback(0, buf, reqn); }
void audioOutCallback1(void *buf, unsigned int reqn, void *userdata) { audioOutCallback(1, buf, reqn); }

void createPitches(float base, float* target)
{
      target[0] = 697;
      target[1] = 770;
      target[2] = 852;
      target[3] = 941;
      target[4] = 1209;
      target[5] = 1336;
      target[6] = 1477;
      target[7] = 1633;
      target[8] = 1;
      target[9] = 1;
      target[10] = 1;
      target[11] = 1;
      target[12] = 1;
}

int main(void)
{
   pspDebugScreenInit();
   SetupCallbacks();
   printf("DTMF Touch Tone Generator by Art 2008!\n");
   printf("Based on Polyphonic sample by Shine\n");

        int i;
   int maxAt = SAMPLE_COUNT / 16;
   for (i = 0; i < SAMPLE_COUNT; i++) {
      float value;
      if (i < maxAt) {
         value = ((float) i) / ((float) maxAt) * 2.0 - 1.0;
      } else {
         value = 1.0 - ((float) (i - maxAt)) / ((float) (SAMPLE_COUNT - maxAt)) * 2.0;
      }
      sample[i] = value;
   }
   float base = 0.0;
   for (i = 0; i < OCTAVE_COUNT; i++) {
      createPitches(base, octaves[i]);
      base *= 2;
   }

   channelStates[0].noteIndex = 0;// nextNote(0);
   channelStates[1].noteIndex = 0;// nextNote(1);

   pspAudioInit();
   pspAudioSetVolume(0, 0x5000, 0x5000);
   pspAudioSetVolume(1, 0x5000, 0x5000);
   pspAudioSetChannelCallback(0, audioOutCallback0, NULL);
   pspAudioSetChannelCallback(1, audioOutCallback1, NULL);


while (done == 0) {
         SceCtrlData xpad;
         sceCtrlSetSamplingMode(1);
         sceCtrlPeekBufferPositive(&xpad, 1);

         if(xpad.Buttons & PSP_CTRL_CROSS) {
         channelStates[0].noteIndex = 1;nextNote(0);
         channelStates[1].noteIndex = 1;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_CIRCLE) {
         channelStates[0].noteIndex = 2;nextNote(0);
         channelStates[1].noteIndex = 2;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_TRIANGLE) {
         channelStates[0].noteIndex = 3;nextNote(0);
         channelStates[1].noteIndex = 3;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_SQUARE) {
         channelStates[0].noteIndex = 4;nextNote(0);
         channelStates[1].noteIndex = 4;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_DOWN) {
         channelStates[0].noteIndex = 5;nextNote(0);
         channelStates[1].noteIndex = 5;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_RIGHT) {
         channelStates[0].noteIndex = 6;nextNote(0);
         channelStates[1].noteIndex = 6;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_UP) {
         channelStates[0].noteIndex = 7;nextNote(0);
         channelStates[1].noteIndex = 7;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_LEFT) {
         channelStates[0].noteIndex = 8;nextNote(0);
         channelStates[1].noteIndex = 8;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_LTRIGGER) {
         channelStates[0].noteIndex = 9;nextNote(0);
         channelStates[1].noteIndex = 9;nextNote(1);
         }

         if(xpad.Buttons & PSP_CTRL_RTRIGGER) {
         channelStates[0].noteIndex = 0;nextNote(0);
         channelStates[1].noteIndex = 0;nextNote(1);
         }

} // while
   done = 1;
   sceKernelExitGame();
   return 0;
}




Cheers, Art.
_________________
If not actually, then potentially.
Back to top
View user's profile Send private message
adrahil



Joined: 16 Mar 2006
Posts: 277

PostPosted: Sun Feb 03, 2008 8:33 pm    Post subject: Reply with quote

Nice sample :)
Back to top
View user's profile Send private message
Art



Joined: 09 Nov 2005
Posts: 647

PostPosted: Sun Feb 03, 2008 10:29 pm    Post subject: Reply with quote

I'm not sure if I want to call a bastardised non-working version of Shine's code a sample yet :D
_________________
If not actually, then potentially.
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Mon Feb 04, 2008 5:01 am    Post subject: Reply with quote

It seems to be using a triangle wave as the sample. Are you sure you shouldn't be using a sine wave instead? Seems to me that anything other than a sine wave would introduce harmonics that would interfere with the recognition of the tone.
Back to top
View user's profile Send private message AIM Address
Art



Joined: 09 Nov 2005
Posts: 647

PostPosted: Mon Feb 04, 2008 6:07 am    Post subject: Reply with quote

That's what you get for fiddling with code you don't understand.
Of course pi isn't defined in it.

I found this:
http://www.ocf.berkeley.edu/~fricke/dtmf.html

Might be more suitable.
_________________
If not actually, then potentially.
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Mon Feb 04, 2008 1:54 pm    Post subject: Reply with quote

Art wrote:

I found this:
http://www.ocf.berkeley.edu/~fricke/dtmf.html


Looks like I was right - that uses a sine wave sample. :)
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group