NXJ Playing Sound Files!!

Post your NXJ projects, project ideas, etc here!

Moderators: 99jonathan, roger, imaqine

Postby 99jonathan » Wed Jul 25, 2007 2:14 am

*cough*

:oops:

trust me, if i had one, i would.

The code should be correct.... it works fine on the computer. The only thing that COULD be causing a problem would be the actual playing of a note. One thing perhaps that i can think of now would be to test for the limits of the frequency before actually playing it. Try putting in something to the likes:

Code: Select all
if(!(tempS>MaxofSoundFrqncy||tempS<MinofSoundFrqncy))
    Sound.playTone(etc....
99jonathan
Moderator
 
Posts: 122
Joined: Thu Mar 01, 2007 5:30 am

Postby CoBB » Wed Jul 25, 2007 1:41 pm

I felt inspired to try this at the lowest level, and rewrote the sound ISR to handle PCM samples. The result is this little piece of code in sound.c:

Code: Select all
const U32 sample_conv[32] = {
  0x00000000, 0x00100000, 0x00100010, 0x00101010,
  0x10101010, 0x10221010, 0x10221022, 0x10222222,
  0x22222222, 0x22522222, 0x22522252, 0x22525252,
  0x52525252, 0x52555252, 0x52555255, 0x52555555,
  0x55555555, 0x556b5555, 0x556b556b, 0x556b6b6b,
  0x6b6b6b6b, 0x6b776b6b, 0x6b776b77, 0x6b777777,
  0x77777777, 0x777f7777, 0x777f777f, 0x777f7f7f,
  0x7f7f7f7f, 0x7fff7f7f, 0x7fff7fff, 0x7fffffff
  /*
  0x00000000, 0x00000001, 0x00000003, 0x00000007,
  0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
  0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
  0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
  0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
  0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
  0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
  0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff
  */
};

U32 sample_count;
U8 sample_buf_id;
U8* sample_ptr;
U32 sample_buf1[16], sample_buf2[16];

void sound_play_sample(U8 *data, U32 length, U32 freq)
{
  *AT91C_SSC_CMR = ((96109714 / 1024) / freq) + 1;
  *AT91C_SSC_PTCR = AT91C_PDC_TXTEN;
  sample_count = length;
  sample_buf_id = 0;
  sample_ptr = data;
  memset(sample_buf1, 0, sizeof(sample_buf1));
  memset(sample_buf2, 0, sizeof(sample_buf2));
  sound_interrupt_enable();
}

void sound_isr_C()
{
  if (sample_count > 0)
  {
    *AT91C_SSC_TNPR = (unsigned int)(sample_buf_id ? sample_buf1 : sample_buf2);
    *AT91C_SSC_TNCR = 16;
    sample_buf_id ^= 1;
    U8 i;
    U32 *sbuf = sample_buf_id ? sample_buf1 : sample_buf2;
    for (i = 0; i < 16; i++)
    {
      *sbuf++ = sample_conv[*sample_ptr >> 3];
      if (i & 1)
      {
        sample_count--;
        sample_ptr++;
      }
    }
    sound_enable();
  }
  else
  {
    sound_disable();
    sound_interrupt_disable();
  }
}

You can start playing a sample by calling sound_play_sample() with a pointer to the 8-bit unsigned PCM data, its length in bytes and the number of samples per second. It will play in the background. If the number of samples is not a multiple of 16, there's a great chance of an ugly audible click at the end for obvious reasons... Unfortunately, it is very noisy, and it doesn't seem to make much difference which conversion table you use. The louder the sound the better the quality, and even a bit of overamplification might help. The easiest way to do this is to rewrite the conversion table above into something nonlinear.

Note that this ISR kills the original tone playing functionality in its present form, but that's trivial to add anyway.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Postby 99jonathan » Wed Jul 25, 2007 3:34 pm

Gj!!

But one reason why i took my previous approach (no buffer) was because big arrays of integers and such are BIG. I don't think that it is a good use of space to use very possibly gigantic arrays.

just my 2 cents...

oh, and gj on the code anyways, i'm not trying to put u down... :wink:

~Jonathan
99jonathan
Moderator
 
Posts: 122
Joined: Thu Mar 01, 2007 5:30 am

Postby CoBB » Wed Jul 25, 2007 4:18 pm

99jonathan wrote:But one reason why i took my previous approach (no buffer) was because big arrays of integers and such are BIG. I don't think that it is a good use of space to use very possibly gigantic arrays.

What buffer? Don’t forget that we’re talking about the NXT, where files are stored in directly addressable memory. And the code above expects 8-bit samples, so there are no huge int arrays. Actually, since the number of sample levels is limited (it’s 32 with my solution), it would probably make sense to make it only 16—I don’t think the sound quality would be much different—and store two samples per byte.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Postby 99jonathan » Wed Jul 25, 2007 8:33 pm

i was talking about my code with the buffer. it reads each note individually as opposed to reading a bunch and then playing them all. :wink:

it would only take a bit of modding, anyways, to get urs to play .wav files directly as opposed to just from arrays.
99jonathan
Moderator
 
Posts: 122
Joined: Thu Mar 01, 2007 5:30 am

Postby CoBB » Wed Jul 25, 2007 9:21 pm

99jonathan wrote:it would only take a bit of modding, anyways, to get urs to play .wav files directly as opposed to just from arrays.

I’m not sure what you mean. Keep in mind that this is an interrupt routine running on the NXT.

Besides, there’s no point in storing, say, 16-bit stereo sounds if we throw away most of the bits anyway, and the available storage space is also rather limited. It’s also best to keep the code as fast as possible, since it runs in an interrupt that’s fired quite frequently.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Previous

Return to NXJ Projects

Who is online

Users browsing this forum: No registered users and 0 guests

more stuff