 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Sun Feb 03, 2008 1:14 pm Post subject: DTMF code sample |
|
|
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 |
|
 |
adrahil
Joined: 16 Mar 2006 Posts: 277
|
Posted: Sun Feb 03, 2008 8:33 pm Post subject: |
|
|
| Nice sample :) |
|
| Back to top |
|
 |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Sun Feb 03, 2008 10:29 pm Post subject: |
|
|
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 |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Mon Feb 04, 2008 5:01 am Post subject: |
|
|
| 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 |
|
 |
Art
Joined: 09 Nov 2005 Posts: 647
|
Posted: Mon Feb 04, 2008 6:07 am Post subject: |
|
|
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 |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Mon Feb 04, 2008 1:54 pm Post subject: |
|
|
Looks like I was right - that uses a sine wave sample. :) |
|
| Back to top |
|
 |
|
|
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
|