Timing of DAC

05 Jan 2012

Sorry total disagree, this is my favourite design based around a SAR you can't beat SAR converter in my eyes. I guess you never try a Flash ADC Gert, but for my projects SAR converter are the best to use:)

/media/uploads/mbed2f/_scaled_panasonic_dr_60_1.jpg

bigger picture http://mbed.org/media/uploads/mbed2f/panasonic_dr_60_1.jpg

http://mbed.org/media/uploads/mbed2f/panasonic_dr_60_2.jpg

/media/uploads/mbed2f/_scaled_panasonic_dr_60_2.jpg

I think maybe I should have called myself panasonic instead:) of Philips:(

06 Jan 2012

Philips Philips wrote:

Sorry total disagree, this is my favourite design based around a SAR you can't beat SAR converter in my eyes. I guess you never try a Flash ADC Gert, but for my projects SAR converter are the best to use:)

For DAC maybe the DSD1792 or PCM1792 is more what you are looking for, for ADC the ads8363 ?

06 Jan 2012

Gert van der Knokke wrote:

Philips Philips wrote:

Sorry total disagree, this is my favourite design based around a SAR you can't beat SAR converter in my eyes. I guess you never try a Flash ADC Gert, but for my projects SAR converter are the best to use:)

For DAC maybe the DSD1792 or PCM1792 is more what you are looking for, for ADC the ads8363 ?

Nope OKi MSM7702 is good enough for me thanks... and so is lpc1768.. it just because my dsylexic brain did not pick up on that it was only a 10 bit dac and I am getting frustrated with the lack of help and the clicking.. and that I should not have being using it above a 10 bit resolution. And you all think I am super intelligent and should know everything like I am physic or something lol

And I myself really like Charles and Yeo designs and concepts theorys and I like reading yeo's blogs and Charles when ever he does a blog entry but Charles he don't really write much on blogs.

I think you was a bit harsh and that you have to at least respect the work that has gone into them both. I admire their work but I admire Panasonic recorder work more:) such as the Panasonic DR60 or QR100

http://diyparadise.com/web/

06 Jan 2012

Philips Philips wrote:

Nope OKi MSM7702 is good enough for me thanks... and so is lpc1768.. it just because my dsylexic brain did not pick up on that it was only a 10 bit dac and I am getting frustrated with the lack of help and the clicking.. and that I should not have being using it above a 10 bit resolution. And you all think I am super intelligent and should know everything like I am physic or something lol

Sorry, thought we were discussing high end audio, that OKI is for speech purpose only.

Quote:

And I myself really like Charles and Yeo designs and concepts theorys and I like reading yeo's blogs and Charles when ever he does a blog entry but Charles he don't really write much on blogs.

I think you was a bit harsh and that you have to at least respect the work that has gone into them both. I admire their work but I admire Panasonic recorder work more:) such as the Panasonic DR60 or QR100

As I said, it is no use on starting discussions on high-end audio :-)

To get a bit further on the clicking and such:

If you, for instance, try repeating a sample and the start and end do not match you will get clicking. You have to average the start and end samples to avoid this. The same will happen if you try and reverse samples: if both ends do not have the same level it will click. You can see this clearly on an oscilloscope (a memory type scope if available)

You could start with a simple waveform, say a sine wave divided into 360 steps. When you play a single wave (360 steps) in a loop both ends will be at zero level and it should produce a nice steady tone.

Now try and shorten the number of samples (say for instance: 270) You will have a maximum negative level at the end of your list of samples and then it suddenly jumps to zero at the beginning. Effect: you get a loud click each time the output goes from maximum negative to zero in almost zero time. Now take a few sample values from the end and from the beginning and average them towards eachother (add them up and divide them by two) and try the loop again. You will notice that it will sound much nicer.

You can understand that with 'random' waveforms (like realtime audio data) the sample values at the beginning and end are bound to be different so you need to average them to avoid 'sudden jumps'.

I hope this makes a bit of sense :-)

06 Jan 2012

Gert van der Knokke wrote:

Philips Philips wrote:

Nope OKi MSM7702 is good enough for me thanks... and so is lpc1768.. it just because my dsylexic brain did not pick up on that it was only a 10 bit dac and I am getting frustrated with the lack of help and the clicking.. and that I should not have being using it above a 10 bit resolution. And you all think I am super intelligent and should know everything like I am physic or something lol

Sorry, thought we were discussing high end audio, that OKI is for speech purpose only.

Quote:

And I myself really like Charles and Yeo designs and concepts theorys and I like reading yeo's blogs and Charles when ever he does a blog entry but Charles he don't really write much on blogs.

I think you was a bit harsh and that you have to at least respect the work that has gone into them both. I admire their work but I admire Panasonic recorder work more:) such as the Panasonic DR60 or QR100

As I said, it is no use on starting discussions on high-end audio :-)

To get a bit further on the clicking and such:

If you, for instance, try repeating a sample and the start and end do not match you will get clicking. You have to average the start and end samples to avoid this. The same will happen if you try and reverse samples: if both ends do not have the same level it will click. You can see this clearly on an oscilloscope (a memory type scope if available)

You could start with a simple waveform, say a sine wave divided into 360 steps. When you play a single wave (360 steps) in a loop both ends will be at zero level and it should produce a nice steady tone.

Now try and shorten the number of samples (say for instance: 270) You will have a maximum negative level at the end of your list of samples and then it suddenly jumps to zero at the beginning. Effect: you get a loud click each time the output goes from maximum negative to zero in almost zero time. Now take a few sample values from the end and from the beginning and average them towards eachother (add them up and divide them by two) and try the loop again. You will notice that it will sound much nicer.

You can understand that with 'random' waveforms (like realtime audio data) the sample values at the beginning and end are bound to be different so you need to average them to avoid 'sudden jumps'.

I hope this makes a bit of sense :-)

I only get the clicking when I have added the reverse code, without the reverse code no clicking happens?

I think after I have change it to 8bit resolution it may fix the problem which I am trying to find out how to do

I have tried to change bSubFrameSize to 0x01 bBitResolution to 8 then WBVAL to 34 and I get bsod error on computer

/* Audio Type I Format */
  AUDIO_FORMAT_TYPE_I_DESC_SZ(1),       /* bLength */
  AUDIO_INTERFACE_DESCRIPTOR_TYPE,      /* bDescriptorType */
  AUDIO_STREAMING_FORMAT_TYPE,          /* bDescriptorSubtype */
  AUDIO_FORMAT_TYPE_I,                  /* bFormatType */
  0x01,                                 /* bNrChannels */
  0x02,                                 /* bSubFrameSize */
  16,                                   /* bBitResolution */
  0x01,                                 /* bSamFreqType */
  B3VAL(32000),                         /* tSamFreq */
/* Endpoint - Standard Descriptor */
  AUDIO_STANDARD_ENDPOINT_DESC_SIZE,    /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,         /* bDescriptorType */
  USB_ENDPOINT_OUT(3),                  /* bEndpointAddress */
  USB_ENDPOINT_TYPE_ISOCHRONOUS,        /* bmAttributes */
  WBVAL(64),                            /* wMaxPacketSize */
  0x01,                                 /* bInterval */
  0x00,                                 /* bRefresh */
  0x00,                                 /* bSynchAddress */

/* Audio Definitions */
#define DATA_FREQ 32000                 /* Audio Data Frequency */
#define P_S       32                    /* Packet Size */
#if USB_DMA
#define P_C       4                     /* Packet Count */
#else
#define P_C       1                     /* Packet Count */
#endif
#define B_S       (8*P_C*P_S)           /* Buffer Size */

I was told to do it like this 1 * 1 *(32 + 1) 34 and we made changes so any value could be enter instead of just number of power of 2 2,4,8,16,32,64

07 Jan 2012

Well thats because when you are not reversing, the samples are 'continuous' from one to the next. (i.e sample 1 follows sample 2).

When you reverse, the one end of the buffer no longer follows from the other (at the boundary). You have no idea if your first sample is close to the last because you are turning the buffer around. One sample at the boundary could be 0 and the other could be 3.3V. When you reverse, these become next to each other resulting in a 'click'. This would be totally expected if you are not doing anything about it.

One suggestion was to average the two adjacent samples at the boundary. Or perhaps you can devise a way to flip your buffer at zero crossings (i.e. when both samples are equal)

07 Jan 2012

I don't know to do it, just like you don't know how to do certain stuff:)

it's 10bit dac yet people have written code to run it a 16 bit resoultion you know

07 Jan 2012

you like this star

http://en.wikipedia.org/wiki/Draco_(constellation)

what is the muse star:)

07 Jan 2012

I keep telling you this

http://en.wikipedia.org/wiki/Dyslexia

here

Dyscalculia— a neurological condition characterized by a problem with basic sense of number and quantity and difficult retrieving rote math facts. Often people with this condition can understand very complex mathematical concepts and principles but have difficulty retrieving basic math facts involving addition and subtraction.

07 Jan 2012

I do not know if visualization helps but here we go:

/media/uploads/gertk/_scaled_sine_wave.jpg

In this example you see a single sinewave (green) with an overlay of the middle part of that sinewave reversed (yellow) If I would play the resulting waveform the analog output would jump from maximum to minimum at about a quarter of the sample and again at threequarter of the sample and that would give a 'click' like this:

/media/uploads/gertk/_scaled_sine_wave_combined.jpg

The red line marks the enormous jump the output has to make.

To eliminate the clicks you could try (as suggested) and find cutting points as close to zero as possible (easier) or average the values so they are smoothed out towards eachother (more difficult).

09 Jan 2012

Gert van der Knokke wrote:

I do not know if visualization helps but here we go:

/media/uploads/gertk/_scaled_sine_wave.jpg

In this example you see a single sinewave (green) with an overlay of the middle part of that sinewave reversed (yellow) If I would play the resulting waveform the analog output would jump from maximum to minimum at about a quarter of the sample and again at threequarter of the sample and that would give a 'click' like this:

/media/uploads/gertk/_scaled_sine_wave_combined.jpg

The red line marks the enormous jump the output has to make.

To eliminate the clicks you could try (as suggested) and find cutting points as close to zero as possible (easier) or average the values so they are smoothed out towards eachother (more difficult).

If you wrote a bit of example code and gave me the complex mathematics would help more be better:) I need to see code mathematics not words.

09 Jan 2012

Maybe something like this might work:

Take 10 sample values at the beginning of the reversed part and 10 sample values at the end and fade them in/out toward zero.

// buffer for our reversed samples (I have used signed int as values)
int samples[MAX_SAMPLES];
// the multiplier we are going to apply to the sample value
float multiplier=0.0;

for (t=0; t<10; t++){
    // fade out end samples to zero
    sample[MAX_SAMPLES-t]=sample[MAX_SAMPLES-t]*multiplier;
    // fade in start samples from zero
    sample[t]=sample[t]*multiplier;
    // increment multiplier so we end up at 1 after 10 samples
    multiplier=multiplier+0.1;
}

This way your reversed sample is 'softened' at the start and end. If the reversed sample is in the middle of a longer (normal) sample you might need to soften the end of the normal part where the reversed part starts and the start of where the normal part continues too. Sorry, it IS complex matter :-)

09 Jan 2012

Ok thanks this is current code, it will take me a while to try to figure out how I am supposed to fit this in to my code

// Hello World example for the USBMIDI library (circular buffer)

#include "mbed.h"
#include "USBAudio.h"
#include "CircBuffer.h"

Serial pc(USBTX, USBRX);

// frequency: 48 kHz
#define FREQ 32000

// 1 channel: mono
#define NB_CHA 1

// length computed: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
#define LENGTH_AUDIO_PACKET 32 * 2 * 1

#define USR_POWERDOWN    (0x104)

int semihost_powerdown() {
    uint32_t arg;
    return __semihost(USR_POWERDOWN, &arg);
}
 

// USBAudio
USBAudio USBaudio(FREQ, NB_CHA, 0x7186, 0x7507);

// speaker connected to the AnalogOut output. The audio stream received over USb will be sent to the speaker
AnalogOut speaker(p18);

// ticker to send data to the speaker at the good frequency
Ticker tic;

// circular buffer where will be stored data to be sent to the speaker
CircBuffer<int16_t> cbuf(LENGTH_AUDIO_PACKET);

// previous value sent to the speaker
uint16_t p_val = 0;

// function executed each 1/FREQ s
void tic_handler() {
    int16_t val;
    float speaker_value;
    unsigned short PlaySample;


    if (cbuf.available() >= 1) {
        cbuf.dequeue(&val);
        speaker_value = (float)val;

        // speaker_value between 0 and 65535
        speaker_value +=  32768.0;

        // adjust according to current volume
        speaker_value *= USBaudio.getVolume();
    } else {
        speaker_value = p_val;
    }
    p_val = speaker_value;
    
    /* ADAMGR: Inserting my May 30th reversing code here!!! */
  {
    static const unsigned int   BufferSize = 20 * 640;
    static unsigned short Buffer[BufferSize];
    
    static int           Index = 0;
    static int           Direction = 1;
    static int           Playback = false;
    static int           ChunkSize = BufferSize;
 
    unsigned short       ReadSample;
 
    /* Default PlaySample to the current sample from USB buffer. */
    PlaySample =  speaker_value;

    
    
    /* Read out the sample from the buffer to be played back */
    if (Playback)
    {
        PlaySample = Buffer[Index];
    }
    
    /* Obtain current audio sample from the USB buffer. */
    ReadSample = (unsigned short)speaker_value;
    
    /* Record the sample into the buffer right where a space was freed up from the PlaySample read above */
    Buffer[Index] = ReadSample;
    
     /* Increment the buffer pointer */
    Index += Direction;
    
    /* Check to see if the chunk has been filled */
    if (Index < 0)
    {
        /* Now have a chunk to be played back */
        Playback = true;
        /* Reverse the direction of playback and recording */
        Direction *= -1;//Direction;
        Index = 0;
    }
    else if (Index >= ChunkSize)
    
    

    {
       /* Now have a chunk to be played back */
        Playback = true;
        /* Reverse the direction of playback and recording */
        Direction *= -1;//Direction;
        Index = ChunkSize - 1;
    }
  }
  

    // send value to the speaker
    speaker.write_u16((uint16_t)PlaySample);
}

int main() {
    int16_t buf[LENGTH_AUDIO_PACKET/2];
    
    semihost_powerdown();

    // attach a function executed each 1/FREQ s
    tic.attach_us(tic_handler, 1000000.0/(float)FREQ);

    while (1) {
        // read an audio packet
        USBaudio.read((uint8_t *)buf);

        // put buffer in the circ buffer
        for(int i = 0; i < LENGTH_AUDIO_PACKET/2; i++) {
            cbuf.queue(buf[i]);
        }
    }
}
10 Jan 2012

I have thought for some time that I just need to take the reversing code out of the timer 0 the Ticker tic..and run a second slower timer or ticker or just have it in the main loop, but I did not know how to transfer the buffer out of the timer routine or if it was possible.

10 Jan 2012

Well I had a bash don't know if this is how you thought it may have been done it gert

// Hello World example for the USBMIDI library (circular buffer)

#include "mbed.h"
#include "USBAudio.h"
#include "CircBuffer.h"

Serial pc(USBTX, USBRX);

// frequency: 48 kHz
#define FREQ 32000

// 1 channel: mono
#define NB_CHA 1

// length computed: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
#define LENGTH_AUDIO_PACKET 32 * 2 * 1

#define USR_POWERDOWN    (0x104)

int semihost_powerdown() {
    uint32_t arg;
    return __semihost(USR_POWERDOWN, &arg);
}
 

// USBAudio
USBAudio USBaudio(FREQ, NB_CHA, 0x7186, 0x7507);

// speaker connected to the AnalogOut output. The audio stream received over USb will be sent to the speaker
AnalogOut speaker(p18);

// ticker to send data to the speaker at the good frequency
Ticker tic;

// circular buffer where will be stored data to be sent to the speaker
CircBuffer<int16_t> cbuf(LENGTH_AUDIO_PACKET);

// previous value sent to the speaker
uint16_t p_val = 0;

// function executed each 1/FREQ s
void tic_handler() {
    int16_t val;
    float speaker_value;
    unsigned short PlaySample;


    if (cbuf.available() >= 1) {
        cbuf.dequeue(&val);
        speaker_value = (float)val;

        // speaker_value between 0 and 65535
        speaker_value +=  32768.0;

        // adjust according to current volume
        speaker_value *= USBaudio.getVolume();
    } else {
        speaker_value = p_val;
    }
    p_val = speaker_value;
    
    /* ADAMGR: Inserting my May 30th reversing code here!!! */
  {
    static const unsigned int   BufferSize = 5 * 1024;
    static unsigned short Buffer[BufferSize];
    // int samples[MAX_SAMPLES];
     
     
    static int           Index = 0;
    static int           Direction = 1;
    static int           Playback = false;
    static int           ChunkSize = BufferSize;
    
   // float multiplier = 0.0;
   
 
    unsigned short       ReadSample;
 
    /* Default PlaySample to the current sample from USB buffer. */
    PlaySample =  speaker_value;

    
    
    /* Read out the sample from the buffer to be played back */
    if (Playback)
    {
        PlaySample = Buffer[Index];
    }
    
    /* Obtain current audio sample from the USB buffer. */
    ReadSample = (unsigned short)speaker_value;
    
    /* Record the sample into the buffer right where a space was freed up from the PlaySample read above */
    Buffer[Index] = ReadSample;
    
     /* Increment the buffer pointer */
    Index += Direction;
    
    /* Check to see if the chunk has been filled */
    if (Index < 0)
    {
        /* Now have a chunk to be played back */
        Playback = true;
        /* Reverse the direction of playback and recording */
        Direction *= -1;//Direction;
        Index = 0;
    }
    else if (Index >= ChunkSize)
    
    

    {
       /* Now have a chunk to be played back */
        Playback = true;
        /* Reverse the direction of playback and recording */
        Direction *= -1;//Direction;
        Index = ChunkSize - 1;
   
  
  int t = 0;
  
  // buffer for our reversed samples (I have used signed int as values)
 int MAX_SAMPLES = 3 * 1024;
int sample[MAX_SAMPLES];
// the multiplier we are going to apply to the sample value
float multiplier=0.0;
  
  MAX_SAMPLES = Index;
  
  for (t=0; t<10; t++){
    // fade out end samples to zero
    sample[MAX_SAMPLES-t]=sample[MAX_SAMPLES-t]*multiplier;
    // fade in start samples from zero
    sample[t]=sample[t]*multiplier;
    // increment multiplier so we end up at 1 after 10 samples
    multiplier=multiplier+0.1;
    
     }
  }
  

    // send value to the speaker
    speaker.write_u16((uint16_t)PlaySample);
}
}
int main() {
    int16_t buf[LENGTH_AUDIO_PACKET/2];
    
    semihost_powerdown();

    // attach a function executed each 1/FREQ s
    tic.attach_us(tic_handler, 1000000.0/(float)FREQ);

    while (1) {
        // read an audio packet
        USBaudio.read((uint8_t *)buf);

        // put buffer in the circ buffer
        for(int i = 0; i < LENGTH_AUDIO_PACKET/2; i++) {
            cbuf.queue(buf[i]);
        }
    }
}
10 Jan 2012

I have this reversing code as well it is complexed tho from http://trac.metadecks.org/browser/sweep/trunk one of my fav audio editors:)

/*
2	 * Sweep, a sound wave editor.
3	 *
4	 * Copyright (C) 2000 Conrad Parker
5	 *
6	 * This program is free software; you can redistribute it and/or modify
7	 * it under the terms of the GNU General Public License as published by
8	 * the Free Software Foundation; either version 2 of the License, or
9	 * (at your option) any later version.
10	 *
11	 * This program is distributed in the hope that it will be useful,
12	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14	 * GNU General Public License for more details.
15	 *
16	 * You should have received a copy of the GNU General Public License
17	 * along with this program; if not, write to the Free Software
18	 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19	 */
20	
21	#include <stdio.h>
22	#include <stdlib.h>
23	#include <string.h>
24	#include <gdk/gdkkeysyms.h>
25	
26	#include <sweep/sweep.h>
27	
28	#include "../src/sweep_app.h" /* XXX */
29	
30	static sw_sample *
31	sounddata_reverse (sw_sample * sample, sw_param_set pset,
32	                   gpointer custom_data)
33	{
34	  GList * gl;
35	  sw_sel * sel;
36	  glong i, sw;
37	  sw_sounddata * sounddata;
38	  sw_format * format;
39	  sw_framecount_t nr_frames;
40	  gpointer d, e, t;
41	
42	  sw_framecount_t op_total, run_total;
43	  sw_framecount_t remaining, n;
44	
45	  gboolean active = TRUE;
46	
47	  sounddata = sample_get_sounddata (sample);
48	  format = sounddata->format;
49	
50	  op_total = sounddata_selection_nr_frames (sounddata) / 200;
51	  if (op_total == 0) op_total = 1;
52	  run_total = 0;
53	
54	  sw = frames_to_bytes (format, 1);
55	  t = alloca (sw);
56	
57	  for (gl = sounddata->sels; active && gl; gl = gl->next) {
58	    sel = (sw_sel *)gl->data;
59	
60	    d = sounddata->data + frames_to_bytes (format, sel->sel_start);
61	    nr_frames = sel->sel_end - sel->sel_start;
62	
63	    e = d + frames_to_bytes (format, nr_frames);
64	   
65	    remaining = nr_frames/2;
66	
67	    while (active && remaining > 0) {
68	      g_mutex_lock (sample->ops_mutex);
69	
70	      if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
71	        active = FALSE;
72	      } else {
73	        n = MIN (remaining, 1024);
74	
75	        for (i = 0; i <= n; i++) {
76	          memcpy (t, d, sw);
77	          memcpy (d, e, sw);
78	          memcpy (e, t, sw);
79	       
80	          d += sw;
81	          e -= sw;
82	        }
83	
84	        remaining -= n;
85	
86	        run_total += n;
87	        sample_set_progress_percent (sample, run_total / op_total);
88	      }
89	
90	      g_mutex_unlock (sample->ops_mutex);
91	    }
92	  }
93	
94	  return sample;
95	}
96	
97	static sw_op_instance *
98	apply_reverse (sw_sample * sample, sw_param_set pset, gpointer custom_data)
99	{
100	  return
101	    perform_filter_op (sample, _("Reverse"),
102	                       (SweepFilter)sounddata_reverse, pset, NULL);
103	}
104	
105	
106	static sw_procedure proc_reverse = {
107	  N_("Reverse"),
108	  N_("Reverse selected regions of a sample"),
109	  "Conrad Parker",
110	  "Copyright (C) 2000",
111	  "http://sweep.sourceforge.net/plugins/reverse",
112	  "Filters/Reverse", /* identifier */
113	  GDK_f, /* accel_key */
114	  GDK_SHIFT_MASK, /* accel_mods */
115	  0, /* nr_params */
116	  NULL, /* param_specs */
117	  NULL, /* suggests() */
118	  apply_reverse,
119	  NULL, /* custom_data */
120	};
121	
122	static GList *
123	reverse_init (void)
124	{
125	  return g_list_append ((GList *)NULL, &proc_reverse);
126	}
127	
128	
129	sw_plugin plugin = {
130	  reverse_init, /* plugin_init */
131	  NULL, /* plugin_cleanup */
132	};

complexed http://trac.metadecks.org/browser/sweep/trunk/src/play.c

10 Jan 2012

The reversing is not the problem :-)

From the source I can recognize the following code for swapping 'frames' (that is multiple samples, often just left and right but with multiple audiotracks it can be more than that)

77              for (i = 0; i <= n; i++) {            // number of frames to swap / 2
76	          memcpy (t, d, sw);                  // save frame to be overwritten in a temp space
77	          memcpy (d, e, sw);                  // copy start to end
78	          memcpy (e, t, sw);                  // copy end to start 
79	       
80	          d += sw;                            // increment start pointer
81	          e -= sw;                            // decrement end pointer
82	        }
83	

So this is not much different except for the more flexible frame size instead of a fixed sample size.

If you do this somewhere inside the middle of a longer sample it will click just as bad as your own code...

As for your earlier message:

The softening needs only to be done once after you have received an audio packet from the USB.

So the order of functions is:

while(1){

 Wait for an audio packet being received 

 Reverse the buffer

 Soften the buffer

 Playback buffer

}
11 Jan 2012

Gert van der Knokke wrote:

The reversing is not the problem :-)

From the source I can recognize the following code for swapping 'frames' (that is multiple samples, often just left and right but with multiple audiotracks it can be more than that)

77              for (i = 0; i <= n; i++) {            // number of frames to swap / 2
76	          memcpy (t, d, sw);                  // save frame to be overwritten in a temp space
77	          memcpy (d, e, sw);                  // copy start to end
78	          memcpy (e, t, sw);                  // copy end to start 
79	       
80	          d += sw;                            // increment start pointer
81	          e -= sw;                            // decrement end pointer
82	        }
83	

So this is not much different except for the more flexible frame size instead of a fixed sample size.

If you do this somewhere inside the middle of a longer sample it will click just as bad as your own code...

As for your earlier message:

The softening needs only to be done once after you have received an audio packet from the USB.

So the order of functions is:

while(1){

 Wait for an audio packet being received 

 Reverse the buffer

 Soften the buffer

 Playback buffer

}

Gert you could have taken the time to browse the trunk for sweep audio editor the code above is not meant for streaming audio, the code is for highlighting a peace of audio and then reversing it, that means after you have recorded the audio and nothing is moving you highlight and press the reverse key from the sweep audio edit.

Sweep audio editor is really complexed I did not post it the play.c file because it's so big that is why I just put the link at the bottom, but you just ignored it.

Please take the time to realized what I posted when I posted sweep, it let you scrub as in mix audio live audio forward or reverse with us or ms delay OK:)

http://www.metadecks.org/software/sweep/

Sweep, a sound wave editor.
3	 *
4	 * Copyright (C) 2000 Conrad Parker
5	 *
6	 * This program is free software; you can redistribute it and/or modify
7	 * it under the terms of the GNU General Public License as published by
8	 * the Free Software Foundation; either version 2 of the License, or
9	 * (at your option) any later version.
10	 *
11	 * This program is distributed in the hope that it will be useful,
12	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14	 * GNU General Public License for more details.
15	 *
16	 * You should have received a copy of the GNU General Public License
17	 * along with this program; if not, write to the Free Software
18	 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19	 */
20	
21	#ifdef HAVE_CONFIG_H
22	#  include <config.h>
23	#endif
24	
25	/* Define this to record all output to files in /tmp */
26	/* #define RECORD_DEMO_FILES */
27	
28	#include <stdio.h>
29	#include <stdlib.h>
30	#include <string.h>
31	#include <sys/time.h>
32	#include <sys/types.h>
33	#include <sys/stat.h>
34	#include <unistd.h>
35	#include <fcntl.h>
36	#include <math.h>
37	#include <sys/ioctl.h>
38	#include <pthread.h>
39	
40	#ifdef RECORD_DEMO_FILES
41	#include <sndfile.h>
42	
43	#if !defined (SNDFILE_1)
44	#error Recording demo files requires libsndfile version 1
45	#endif
46	
47	#endif
48	
49	#include <sweep/sweep_types.h>
50	#include <sweep/sweep_sample.h>
51	#include <sweep/sweep_typeconvert.h>
52	
53	#include "play.h"
54	#include "head.h"
55	#include "driver.h"
56	#include "preferences.h"
57	#include "sample-display.h"
58	
59	/*#define DEBUG*/
60	
61	#define SCRUB_SLACKNESS 2.0
62	
63	#define USE_MONITOR_KEY "UseMonitor"
64	
65	static GMutex * play_mutex = NULL;
66	
67	static sw_handle * main_handle = NULL;
68	static sw_handle * monitor_handle = NULL;
69	
70	static GList * active_main_heads = NULL;
71	static GList * active_monitor_heads = NULL;
72	
73	/*static int realoffset = 0;*/
74	static sw_sample * prev_sample = NULL;
75	static pthread_t player_thread = (pthread_t)-1;
76	
77	static gboolean stop_all = FALSE;
78	
79	static sw_audio_t * pbuf = NULL, * devbuf = NULL;
80	static int pbuf_chans = 0, devbuf_chans = 0;
81	
82	
83	/*
84	 * update_playmarker ()
85	 *
86	 * Update the position of the playback marker line for the sample
87	 * being played.
88	 *
89	 * Called within the main sweep interface thread.
90	 * gtk_idle will keep calling this function as long as this sample is
91	 * playing, unless otherwise stopped.
92	 */
93	static gint
94	update_playmarker (gpointer data)
95	{
96	  sw_sample * s = (sw_sample *)data;
97	  sw_head * head = s->play_head;
98	
99	  if (!sample_bank_contains (s)) {
100	    return FALSE;
101	  } else if (!head->going) {
102	
103	#ifdef DEBUG
104	    g_print ("update_playmarker: !head->going\n");
105	#endif
106	    s->playmarker_tag = 0;
107	
108	    /* Set user offset to correct offset */
109	    if (head->previewing) {
110	      sample_set_playmarker (s, head->stop_offset, TRUE);
111	      head_set_previewing (head, FALSE);
112	    } else {
113	      sample_set_playmarker (s, (sw_framecount_t)head->offset, TRUE);
114	    }
115	   
116	    /* As this may have been stopped by the player thread, refresh the
117	     * interface */
118	    head_set_going (head, FALSE);
119	    sample_refresh_playmode (s);
120	   
121	    return FALSE;
122	  } else {
123	    sample_set_playmarker (s, head->realoffset, FALSE);
124	
125	    return TRUE;
126	  }
127	}
128	
129	static void
130	start_playmarker (sw_sample * s)
131	{
132	  if (s->playmarker_tag > 0) {
133	    g_source_remove (s->playmarker_tag);
134	  }
135	
136	  s->playmarker_tag =
137	    g_timeout_add ((guint32)30,
138	                     (GSourceFunc) update_playmarker,
139	                     (gpointer)s);
140	}
141	
142	static sw_framecount_t
143	head_read_unrestricted (sw_head * head, sw_audio_t * buf,
144	                        sw_framecount_t count, int driver_rate)
145	{
146	  sw_sample * sample = head->sample;
147	  sw_sounddata * sounddata = sample->sounddata;
148	  sw_format * f = sounddata->format;
149	  sw_audio_t * d;
150	  gdouble po = 0.0, p;
151	  gfloat relpitch;
152	  sw_framecount_t i, j, b;
153	  gint si=0, si_next = 0;
154	  gboolean interpolate = FALSE;
155	  gboolean do_smoothing = FALSE;
156	  sw_framecount_t last_user_offset = -1;
157	  int pbuf_size = count * f->channels;
158	  gdouble scrub_rate = f->rate / 30.0;
159	
160	  d = (sw_audio_t *)sounddata->data;
161	
162	  b = 0;
163	
164	  po = head->offset;
165	
166	  /* compensate for sampling rate of driver */
167	  relpitch = (gfloat)((gdouble)f->rate / (gdouble)driver_rate);
168	 
169	  for (i = 0; i < count; i++) {
170	    if (head->mute || sample->user_offset == last_user_offset) {
171	      for (j = 0; j < f->channels; j++) {
172	        buf[b] = 0.0;
173	        b++;
174	      }
175	    } else {
176	      si = (int)floor(po);
177	     
178	      interpolate = (si < sounddata->nr_frames);
179	     
180	      p = po - (gdouble)si;
181	      si *= f->channels;
182	      g_mutex_lock(head->sample->sounddata->data_mutex);
183	
184	      if (interpolate) {
185	        si_next = si+f->channels;
186	        for (j = 0; j < f->channels; j++) {
187	         buf[b] = head->gain * (((sw_audio_t *)head->sample->sounddata->data)[si] * p + ((sw_audio_t *)head->sample->sounddata->data)[si_next] * (1 - p));
188	          if (do_smoothing) {
189	            sw_framecount_t b1, b2;
190	            b1 = (b - f->channels + pbuf_size) % pbuf_size;
191	            b2 = (b1 - f->channels + pbuf_size) % pbuf_size;
192	            buf[b] += buf[b] * 2.0;
193	            buf[b] += buf[b1] * 3.0 + buf[b2] * 4.0;
194	            buf[b] /= 10.0;
195	          }
196	          b++; si++; si_next++;
197	        }
198	      } else {
199	        for (j = 0; j < f->channels; j++) {
200	         buf[b] = head->gain * ((sw_audio_t *)head->sample->sounddata->data)[si];
201	          if (do_smoothing) {
202	            sw_framecount_t b1, b2;
203	            b1 = (b - f->channels + pbuf_size) % pbuf_size;
204	            b2 = (b1 - f->channels + pbuf_size) % pbuf_size;
205	            buf[b] += buf[b] * 2.0;
206	            buf[b] += buf[b1] * 3.0 + buf[b2] * 4.0;
207	            buf[b] /= 10.0;
208	          }
209	          b++; si++;
210	        }
211	      }
212	     g_mutex_unlock(head->sample->sounddata->data_mutex);
213	    }
214	
215	    if (head->scrubbing) {
216	      gfloat new_delta;
217	
218	      if (sample->by_user) {
219	        new_delta = (sample->user_offset - po) / scrub_rate;
220	       
221	        head->delta = head->delta * 0.9 + new_delta * 0.1;
222	       
223	        sample->by_user = FALSE;
224	       
225	        last_user_offset = sample->user_offset;
226	      } else  {
227	        gfloat new_po, u_po = (gdouble)sample->user_offset;
228	
229	        new_delta = (sample->user_offset - po) / scrub_rate;
230	       
231	        head->delta = head->delta * 0.99 + new_delta * 0.01;
232	       
233	        new_po = po + (head->delta * relpitch);
234	       
235	        if ((head->delta < 0 && new_po < u_po) ||
236	            (head->delta > 0 && new_po > u_po)) {
237	          po = u_po;
238	          head->delta = 0.0;
239	        }
240	      }
241	     
242	      do_smoothing = TRUE;
243	
244	    } else {
245	      gfloat tdelta = head->rate * sample->rate;
246	      gfloat hdelta = head->delta * (head->reverse ? -1.0 : 1.0);
247	
248	      if (sample->by_user) {
249	        head->offset = (gdouble)sample->user_offset;
250	        po = head->offset;
251	        head->delta = tdelta;
252	
253	        sample->by_user = FALSE;
254	        do_smoothing = TRUE;
255	
256	        last_user_offset = sample->user_offset;
257	      }
258	
259	      if (hdelta < -0.3 * tdelta || hdelta > 1.001 * tdelta) {
260	        head->delta *= 0.9999;
261	      } else if (hdelta < 0.7 * tdelta) {
262	        head->delta = 0.8 * tdelta * (head->reverse ? -1.0 : 1.0);
263	      } else if (hdelta < .999 * tdelta) {
264	        head->delta *= 1.0001;
265	      } else {
266	        head->delta = tdelta * (head->reverse ? -1.0 : 1.0);
267	      }
268	
269	      do_smoothing = FALSE;
270	    }
271	
272	    po += head->delta * relpitch;
273	
274	    {
275	      gdouble nr_frames = (gdouble)sample->sounddata->nr_frames;
276	      if (head->looping) {
277	        while (po < 0.0) po += nr_frames;
278	        while (po > nr_frames) po -= nr_frames;
279	      } else {
280	        if (po < 0.0) po = 0.0;
281	        else if (po > nr_frames) po = nr_frames;
282	      }
283	    }
284	
285	    head->offset = po;
286	
287	  }
288	
289	  return count;
290	}
291	
292	sw_framecount_t
293	head_read (sw_head * head, sw_audio_t * buf, sw_framecount_t count,
294	           int driver_rate)
295	{
296	  sw_sample * sample = head->sample;
297	  sw_sounddata * sounddata = sample->sounddata;
298	  sw_format * f = sounddata->format;
299	  sw_framecount_t head_offset;
300	  sw_framecount_t remaining = count, written = 0, n = 0;
301	  sw_framecount_t delta, bound;
302	  GList * gl;
303	  sw_sel * sel, * osel;
304	
305	  while (head->going && remaining > 0) {
306	    n = 0;
307	
308	    if (head->restricted /* && !head->scrubbing */) {
309	      g_mutex_lock (sounddata->sels_mutex);
310	
311	      if (g_list_length (sounddata->sels) == 0) {
312	        g_mutex_unlock (sounddata->sels_mutex);
313	
314	        if (head->previewing && !head->scrubbing) {
315	          if (head->reverse) {
316	            n = MIN (remaining, head->offset - head->stop_offset);
317	          } else {
318	            n = MIN (remaining, head->stop_offset - head->offset);
319	          }
320	          goto got_n;
321	
322	        } else {
323	          goto zero_pad;
324	        }
325	      }
326	
327	      if (head->previewing && !head->scrubbing) {
328	        /* Find selection region that offset is or should be playing to */
329	        if (head->reverse) {
330	          osel = NULL;
331	          for (gl = g_list_last (sounddata->sels); gl; gl = gl->prev) {
332	            sel = (sw_sel *)gl->data;
333	           
334	            if (osel && ((sw_framecount_t)head->offset > osel->sel_start))
335	              head->offset = osel->sel_start;
336	
337	            osel = sel;
338	
339	            head_offset = (sw_framecount_t)head->offset;
340	           
341	            if (head_offset > sel->sel_end) {
342	              n = MIN (remaining, head_offset - sel->sel_end);
343	              break;
344	            }
345	          }
346	
347	          /* If now at start of first selection region ... */
348	          if (gl == NULL && osel != NULL) {
349	            if ((sw_framecount_t)head->offset > osel->sel_start)
350	              head->offset = osel->sel_start;
351	
352	            head_offset = (sw_framecount_t)head->offset;
353	           
354	            /* continue 1 second */
355	            delta = time_to_frames (sounddata->format, 1.0);
356	            bound = MAX((osel->sel_start - delta), 0);
357	            if (head_offset > bound) {
358	              n = MIN (remaining, head_offset - bound);
359	            }
360	          }
361	
362	        } else {
363	          osel = NULL;
364	          for (gl = sounddata->sels; gl; gl = gl->next) {
365	            sel = (sw_sel *)gl->data;
366	           
367	            if (osel && ((sw_framecount_t)head->offset < osel->sel_end))
368	              head->offset = osel->sel_end;
369	
370	            osel = sel;
371	           
372	            head_offset = (sw_framecount_t)head->offset;
373	
374	            if (head_offset < sel->sel_start) {
375	              n = MIN (remaining, sel->sel_start - head_offset);
376	              break;
377	            }
378	          }
379	         
380	          /* If now at end of last selection region ... */
381	          if (gl == NULL && osel != NULL) {
382	            if ((sw_framecount_t)head->offset < osel->sel_end)
383	              head->offset = osel->sel_end;
384	
385	            head_offset = head->offset;
386	
387	            /* continue 1 second */
388	            delta = time_to_frames (sounddata->format, 1.0);
389	            bound = MIN ((osel->sel_end + delta), sounddata->nr_frames);
390	            if (head_offset < bound) {
391	              n = MIN (remaining, bound - head_offset);
392	            }
393	          }
394	        }
395	      } else {
396	        /* Find selection region that offset is or should be in */
397	        if (head->reverse) {
398	          for (gl = g_list_last (sounddata->sels); gl; gl = gl->prev) {
399	            sel = (sw_sel *)gl->data;
400	           
401	            if ((sw_framecount_t)head->offset > sel->sel_end)
402	              head->offset = sel->sel_end;
403	           
404	            if ((sw_framecount_t)head->offset > sel->sel_start) {
405	              n = MIN (remaining, (sw_framecount_t)head->offset - sel->sel_start);
406	              break;
407	            }
408	          }
409	        } else {
410	          for (gl = sounddata->sels; gl; gl = gl->next) {
411	            sel = (sw_sel *)gl->data;
412	           
413	            if ((sw_framecount_t)head->offset < sel->sel_start)
414	              head->offset = sel->sel_start;
415	           
416	            if ((sw_framecount_t)head->offset < sel->sel_end) {
417	              n = MIN (remaining, sel->sel_end - (sw_framecount_t)head->offset);
418	              break;
419	            }
420	          }
421	        }
422	      }
423	
424	      g_mutex_unlock (sounddata->sels_mutex);
425	
426	    } else { /* unrestricted */
427	      if (head->previewing && !head->scrubbing) {
428	        if (head->reverse) {
429	          n = MIN (remaining, (sw_framecount_t)head->offset - head->stop_offset);
430	        } else {
431	          n = MIN (remaining, head->stop_offset - (sw_framecount_t)head->offset);
432	        }
433	      } else {
434	        if (head->reverse) {
435	          n = MIN (remaining, (sw_framecount_t)head->offset);
436	        } else {
437	          n = MIN (remaining, sounddata->nr_frames - (sw_framecount_t)head->offset);
438	        }
439	      }
440	    }
441	
442	  got_n:
443	
444	    if (n == 0) {
445	      if (head->previewing) {
446	        head->offset = head->stop_offset;
447	      } else if (!head->restricted || sounddata->sels == NULL) {
448	        head->offset = head->reverse ? sounddata->nr_frames : 0;
449	      } else {
450	        g_mutex_lock (sounddata->sels_mutex);
451	        if (head->reverse) {
452	          gl = g_list_last (sounddata->sels);
453	          sel = (sw_sel *)gl->data;
454	          head->offset = sel->sel_end;
455	        } else {
456	          gl = sounddata->sels;
457	          sel = (sw_sel *)gl->data;
458	          head->offset = sel->sel_start;
459	        }
460	        g_mutex_unlock (sounddata->sels_mutex);
461	      }
462	
463	      if (!head->looping || head->previewing) {
464	        head->going = FALSE;
465	      }
466	    } else {
467	      if (n < 0) {
468	#ifdef DEBUG
469	        printf ("n = %d\n", n);
470	#endif
471	        head->going = FALSE;
472	#ifdef DEUBG
473	      } else if (n > count) {
474	        printf ("n = %d \t>\tcount = %d\n", n, count);
475	#endif
476	      } else {
477	      written += head_read_unrestricted (head, buf, n, driver_rate);
478	      buf += (int)frames_to_samples (f, n);
479	      remaining -= n;
480	      }
481	    }
482	  }
483	
484	 zero_pad:
485	
486	  if (remaining > 0) {
487	    n = frames_to_bytes (f, remaining);
488	    memset (buf, 0, n);
489	    written += remaining;
490	  }
491	
492	  return written;
493	}
494	
495	/* initialise a head for playback */
496	static void
497	head_init_playback (sw_sample * s)
498	{
499	  sw_head * head = s->play_head;
500	  GList * gl;
501	  sw_sel * sel;
502	  sw_framecount_t sels_start, sels_end;
503	  sw_framecount_t delta;
504	
505	  /*  g_mutex_lock (s->play_mutex);*/
506	
507	  s->by_user = FALSE;
508	
509	  if (!head->going) {
510	    head_set_offset (head, s->user_offset);
511	    head->delta = head->rate * s->rate;
512	  }
513	
514	
515	  if (head->restricted) {
516	    g_mutex_lock (s->sounddata->sels_mutex);
517	
518	    if ((gl = s->sounddata->sels) != NULL) {
519	      sel = (sw_sel *)gl->data;
520	      sels_start = sel->sel_start;
521	     
522	      gl = g_list_last (s->sounddata->sels);
523	     
524	      sel = (sw_sel *)gl->data;
525	      sels_end = sel->sel_end;
526	      g_mutex_unlock (s->sounddata->sels_mutex);
527	     
528	      if (head->previewing) {
529	        /* preroll 1 second */
530	        delta = time_to_frames (s->sounddata->format, 1.0);
531	       
532	        if (head->reverse) {
533	          head_set_offset (head, sels_end + delta);
534	        } else {
535	          head_set_offset (head, sels_start - delta);
536	        }
537	       
538	        head_set_offset (head,
539	                         CLAMP((sw_framecount_t)head->offset, 0, s->sounddata->nr_frames));
540	      } else {
541	        if (head->reverse && head->offset <= sels_start) {
542	          head_set_offset (head, sels_end);
543	        } else if (!head->reverse && head->offset >= sels_end) {
544	          head_set_offset (head, sels_start);
545	        }
546	      }
547	    } else if (head->previewing) {
548	        /* preroll 1 second */
549	        delta = time_to_frames (s->sounddata->format, 1.0);
550	       
551	        if (head->reverse) {
552	          head_set_offset (head, head->offset + delta);
553	        } else {
554	          head_set_offset (head, head->offset - delta);
555	        }
556	       
557	        head_set_offset (head,
558	                         CLAMP(head->offset, 0, s->sounddata->nr_frames));
559	    }
560	  } else {
561	
562	    if (head->previewing) {
563	      /* preroll 1 second */
564	      delta = time_to_frames (s->sounddata->format, 1.0);
565	      if (head->reverse) head_set_offset (head, head->offset + delta);
566	      else head_set_offset (head, head->offset - delta);
567	    }
568	
569	    if (head->reverse && head->offset <= 0) {
570	      head_set_offset (head,  s->sounddata->nr_frames);
571	    } else if (!head->reverse && head->offset >= s->sounddata->nr_frames) {
572	      head_set_offset (head, 0);
573	    }
574	  }
575	
576	  /*  g_mutex_unlock (s->play_mutex);*/
577	}
578	
579	static void
580	channel_convert_adding (sw_audio_t * src, int src_channels,
581	                        sw_audio_t * dest, int dest_channels,
582	                        sw_framecount_t n)
583	{
584	  int j;
585	  sw_framecount_t i, b = 0;
586	  sw_audio_intermediate_t a;
587	
588	  if (src_channels == 1) { /* mix mono data up */
589	    for (i = 0; i < n; i++) {
590	      for (j = 0; j < dest_channels; j++) {
591	        dest[b] += src[i];
592	        b++;
593	      }
594	    }
595	  } else if (dest_channels == 1) { /* mix down to mono */
596	    for (i = 0; i < n; i++) {
597	      a = 0.0;
598	      for (j = 0; j < src_channels; j++) {
599	        a += src[b];
600	        b++;
601	      }
602	      a /= (sw_audio_intermediate_t)src_channels;
603	      dest[i] += (sw_audio_t)a;
604	    }
605	  } else if (src_channels < dest_channels) { /* copy to first channels */
606	    for (i = 0; i < n; i++) {
607	      for (j = 0; j < src_channels; j++) {
608	        dest[i * dest_channels + j] += src[b];
609	        b++;
610	      }
611	    }
612	  } else if (dest_channels < src_channels) { /* copy first channels only */
613	    for (i = 0; i < n; i++) {
614	      for (j = 0; j < dest_channels; j++) {
615	        dest[b] += src[i * src_channels + j];
616	        b++;
617	      }
618	    }
619	  } else if (src_channels == dest_channels) { /* just add */
620	    for (i = 0; i < n * src_channels; i ++) {
621	      dest[i] += src[i];
622	    }
623	  }
624	}
625	
626	static void
627	play_head_update_device (sw_head * head)
628	{
629	  g_mutex_lock (play_mutex);
630	  g_mutex_lock (head->head_mutex);
631	
632	  if (head->monitor) {
633	    if (g_list_find (active_monitor_heads, head) == 0) {
634	      active_monitor_heads = g_list_append (active_monitor_heads, head);
635	    }
636	    active_main_heads = g_list_remove (active_main_heads, head);
637	  } else {
638	    if (g_list_find (active_main_heads, head) == 0) {
639	      active_main_heads = g_list_append (active_main_heads, head);
640	    }
641	    active_monitor_heads = g_list_remove (active_monitor_heads, head);
642	  }
643	
644	  g_mutex_unlock (head->head_mutex);
645	  g_mutex_unlock (play_mutex);
646	}
647	
648	#ifdef RECORD_DEMO_FILES
649	static gchar *
650	generate_demo_filename (void)
651	{
652	  return g_strdup_printf ("/tmp/sweep-demo-%d.au", getpid ());
653	}
654	#endif
655	
656	#define PSIZ 64
657	
658	static void
659	prepare_to_play_heads (GList * heads, sw_handle * handle)
660	{
661	  sw_head * head;
662	  sw_format * f;
663	
664	  GList * gl;
665	
666	  if ((gl = heads) != NULL) {
667	    head = (sw_head *)gl->data;
668	
669	    f = head->sample->sounddata->format;
670	   
671	    if (f->channels > pbuf_chans) {
672	      pbuf = g_realloc (pbuf, PSIZ * f->channels * sizeof (sw_audio_t));
673	      pbuf_chans = f->channels;
674	    }
675	  }
676	
677	  device_wait (handle);
678	
679	  return;
680	}
681	
682	static void
683	play_heads (GList ** heads, sw_handle * handle)
684	{
685	  sw_sample * s;
686	  sw_head * head;
687	  sw_format * f;
688	  sw_framecount_t n;
689	
690	  GList * gl, * gl_next;
691	
692	  if (*heads == NULL) return;
693	
694	  n = PSIZ;
695	 
696	  for (gl = *heads; gl; gl = gl_next) {
697	
698	    g_mutex_lock (play_mutex);
699	    head = (sw_head *)gl->data;
700	    gl_next = gl->next;
701	    g_mutex_unlock (play_mutex);
702	
703	    if (!head) {
704	      /* XXX: wtf??? */
705	      return;
706	    } else if (!head->going || !sample_bank_contains (head->sample)) {
707	      g_mutex_lock (play_mutex);
708	      *heads = g_list_remove (*heads, head);
709	      g_mutex_unlock (play_mutex);
710	    } else {
711	      s = head->sample;
712	      f = s->sounddata->format;
713	         
714	      if (f->channels > pbuf_chans) {
715	        pbuf = g_realloc (pbuf, n * f->channels * sizeof (sw_audio_t));
716	        pbuf_chans = f->channels;
717	      }
718	
719	      head_read (head, pbuf, n, handle->driver_rate);
720	
721	      channel_convert_adding (pbuf, f->channels, devbuf,
722	                              handle->driver_channels, n);
723	       
724	      /* XXX: store the head->offset NOW for device_offset referencing */
725	         
726	      g_mutex_lock (s->play_mutex);
727	         
728	      head->realoffset = device_offset (handle);
729	      if (head->realoffset == -1) {
730	        head->realoffset = head->offset;
731	      }
732	       
733	      head->offset = head->realoffset;
734	         
735	      if (s->by_user /* && s->play_scrubbing */) {
736	        /*head->offset = s->user_offset;*/
737	      } else {
738	        if (!head->scrubbing) s->user_offset = head->realoffset;
739	      }
740	         
741	      /*        if (!head->going) active = FALSE;*/
742	         
743	      g_mutex_unlock (s->play_mutex);
744	    }
745	  }
746	
747	  return;
748	}
749	
750	/* how many inactive writes to do before closing */
751	#define INACTIVE_TIMEOUT 256
752	
753	static gboolean
754	monitor_active (void)
755	{
756	  int * use_monitor;
757	
758	  use_monitor = prefs_get_int (USE_MONITOR_KEY);
759	
760	  if (use_monitor == NULL) return 0;
761	  else return (*use_monitor != 0);
762	}
763	
764	static void
765	play_active_heads (void)
766	{
767	  sw_framecount_t count;
768	  int inactive_writes = 0;
769	  GList * gl;
770	  sw_head * head;
771	  sw_format * f;
772	  int max_driver_chans = 0;
773	
774	  gboolean use_monitor;
775	
776	#ifdef RECORD_DEMO_FILES
777	  gchar * filename;
778	  SNDFILE * sndfile = NULL;
779	  SF_INFO sfinfo;
780	#endif
781	
782	  if (!active_main_heads && !active_monitor_heads) return;
783	
784	  use_monitor = (monitor_handle != NULL);
785	
786	  if (use_monitor) {
787	    if ((gl = active_monitor_heads)) {
788	      head = (sw_head *)gl->data;
789	      f = head->sample->sounddata->format;
790	     
791	      device_setup (monitor_handle, f);
792	    } else if ((gl = active_main_heads)) {
793	      head = (sw_head *)gl->data;
794	      f = head->sample->sounddata->format;
795	     
796	      device_setup (monitor_handle, f);
797	    }
798	  }
799	
800	  if ((gl = active_main_heads)) {
801	    head = (sw_head *)gl->data;
802	    f = head->sample->sounddata->format;
803	
804	    device_setup (main_handle, f);
805	
806	#ifdef RECORD_DEMO_FILES   
807	    filename = generate_demo_filename ();
808	    sfinfo.samplerate = f->rate;
809	    sfinfo.channels = handle->driver_channels;
810	    sfinfo.format = SF_FORMAT_AU | SF_FORMAT_FLOAT | SF_ENDIAN_CPU;
811	    sndfile = sf_open (filename, SFM_WRITE, &sfinfo);
812	    if (sndfile == NULL) sf_perror (NULL);
813	    else printf ("Writing to %s\n", filename);
814	#endif
815	  } else if ((gl = active_monitor_heads)) {
816	    head = (sw_head *)gl->data;
817	    f = head->sample->sounddata->format;
818	
819	    device_setup (main_handle, f);
820	  } else {
821	    return;
822	  }
823	
824	  if (use_monitor) {
825	    max_driver_chans = MAX (main_handle->driver_channels,
826	                            monitor_handle->driver_channels);
827	  } else {
828	    max_driver_chans = main_handle->driver_channels;
829	  }
830	
831	  if (max_driver_chans > devbuf_chans) {
832	    devbuf = g_realloc (devbuf,
833	                        PSIZ * max_driver_chans * sizeof (sw_audio_t));
834	    devbuf_chans = max_driver_chans;
835	  }
836	
837	  while (!stop_all && inactive_writes < INACTIVE_TIMEOUT) {
838	
839	    if (active_main_heads == NULL && active_monitor_heads == NULL) {
840	      inactive_writes++;
841	    } else {
842	      inactive_writes = 0;
843	    }
844	
845	    g_mutex_lock (play_mutex);
846	    if (use_monitor) {
847	      prepare_to_play_heads (active_monitor_heads, monitor_handle);
848	      prepare_to_play_heads (active_main_heads, main_handle);
849	    } else {
850	      prepare_to_play_heads (active_monitor_heads, main_handle);
851	      prepare_to_play_heads (active_main_heads, main_handle);
852	    }
853	    g_mutex_unlock (play_mutex);
854	
855	    if (use_monitor) {
856	      count = PSIZ * monitor_handle->driver_channels;
857	      memset (devbuf, 0, count * sizeof (sw_audio_t));
858	      play_heads (&active_monitor_heads, monitor_handle);
859	      device_write (monitor_handle, devbuf, count); 
860	     
861	      count = PSIZ * main_handle->driver_channels;
862	      memset (devbuf, 0, count * sizeof (sw_audio_t));
863	      play_heads (&active_main_heads, main_handle);
864	      device_write (main_handle, devbuf, count);
865	    } else {
866	      count = PSIZ * main_handle->driver_channels;
867	      memset (devbuf, 0, count * sizeof (sw_audio_t));
868	      play_heads (&active_monitor_heads, main_handle);
869	      play_heads (&active_main_heads, main_handle);
870	      device_write (main_handle, devbuf, count); 
871	    }
872	
873	#ifdef RECORD_DEMO_FILES
874	    if (sndfile)
875	      sf_writef_float (sndfile, devbuf, count / main_handle->driver_channels);
876	#endif
877	  }
878	
879	  if (use_monitor) {
880	    device_reset (monitor_handle);
881	    device_close (monitor_handle);
882	  }
883	
884	  device_reset (main_handle);
885	  device_close (main_handle);
886	
887	#ifdef RECORD_DEMO_FILES
888	  if (sndfile) {
889	    printf ("Closing %s\n", filename);
890	    sf_close (sndfile);
891	  }
892	#endif
893	
894	  player_thread = (pthread_t) -1;
895	}
896	
897	static gboolean
898	ensure_playing (void)
899	{
900	  sw_handle * h;
901	
902	  if (player_thread == (pthread_t) -1) {
903	    if ((h = device_open (0, O_WRONLY)) != NULL) {
904	      main_handle = h;
905	      if (monitor_active()) {
906	        monitor_handle = device_open (1, O_WRONLY);
907	      } else {
908	        monitor_handle = NULL;
909	      }
910	
911	      pthread_create (&player_thread, NULL, (void *) (*play_active_heads),
912	                      NULL);
913	      return TRUE;
914	    } else {
915	      return FALSE;
916	    }
917	  }
918	
919	  return TRUE;
920	}
921	
922	void
923	sample_play (sw_sample * sample)
924	{
925	  sw_head * head = sample->play_head;
926	
927	  play_head_update_device (head);
928	  head_init_playback (sample);
929	
930	  head_set_going (head, TRUE);
931	
932	  sample_refresh_playmode (sample);
933	
934	  if (ensure_playing()) {
935	    start_playmarker (sample);
936	  } else {
937	    head_set_going (head, FALSE);
938	    sample_refresh_playmode (sample);
939	  }
940	}
941	
942	void
943	sample_update_device (sw_sample * sample)
944	{
945	  sw_head * head = sample->play_head;
946	
947	  if (!head->going) return;
948	
949	  play_head_update_device (head);
950	}
951	
952	void
953	play_view_all (sw_view * view)
954	{
955	  sw_sample * s = view->sample;
956	  sw_head * head = s->play_head;
957	
958	  sample_set_stop_offset (s);
959	  sample_set_previewing (s, FALSE);
960	   
961	  prev_sample = s;
962	
963	  head_set_restricted (head, FALSE);
964	
965	  sample_play (s);
966	}
967	
968	void
969	play_view_sel (sw_view * view)
970	{
971	  sw_sample * s = view->sample;
972	  sw_head * head = s->play_head;
973	
974	  if (s->sounddata->sels == NULL) {
975	    head_set_going (head, FALSE);
976	    sample_refresh_playmode (s);
977	    return;
978	  }
979	
980	  sample_set_stop_offset (s);
981	  sample_set_previewing (s, FALSE);
982	
983	  prev_sample = s;
984	
985	  head_set_restricted (head, TRUE);
986	
987	  sample_play (s);
988	}
989	
990	void
991	play_preroll (sw_view * view)
992	{
993	  sw_sample * s = view->sample;
994	  sw_head * head = s->play_head;
995	
996	  sample_set_stop_offset (s);
997	  sample_set_previewing (s, TRUE);
998	  sample_set_scrubbing (s, FALSE);
999	   
1000	  prev_sample = s;
1001	
1002	  head_set_restricted (head, FALSE);
1003	
1004	  sample_play (s);
1005	}
1006	
1007	void
1008	play_preview_cut (sw_view * view)
1009	{
1010	  sw_sample * s = view->sample;
1011	  sw_head * head = s->play_head;
1012	
1013	  if (s->sounddata->sels == NULL) {
1014	    head_set_going (head, FALSE);
1015	    sample_refresh_playmode (s);
1016	    return;
1017	  }
1018	
1019	  sample_set_stop_offset (s);
1020	  sample_set_previewing (s, TRUE);
1021	  sample_set_scrubbing (s, FALSE);
1022	   
1023	  prev_sample = s;
1024	
1025	  head_set_restricted (head, TRUE);
1026	
1027	  sample_play (s);
1028	}
1029	
1030	void
1031	play_view_all_pitch (sw_view * view, gfloat pitch)
1032	{
1033	  sw_sample * s = view->sample;
1034	  sw_head * head = s->play_head;
1035	  sw_framecount_t mouse_offset;
1036	
1037	  mouse_offset =
1038	    sample_display_get_mouse_offset (SAMPLE_DISPLAY(view->display));
1039	  sample_set_playmarker (s, mouse_offset, TRUE);
1040	
1041	  sample_set_stop_offset (s);
1042	  sample_set_previewing (s, FALSE);
1043	
1044	  prev_sample = s;
1045	
1046	  head_set_restricted (head, FALSE);
1047	  head_set_rate (head, pitch);
1048	
1049	  sample_play (s);
1050	}
1051	
1052	void
1053	stop_all_playback (void)
1054	{
1055	  stop_all = TRUE;
1056	  g_list_free (active_main_heads);
1057	  active_main_heads = NULL;
1058	}
1059	
1060	void
1061	pause_playback (sw_sample * s)
1062	{
1063	  sw_head * head;
1064	
1065	  if (s == NULL) return;
1066	
1067	  head = s->play_head;
1068	
1069	  if (head->going) {
1070	    head_set_going (head, FALSE);
1071	  }
1072	
1073	  sample_set_stop_offset (s);
1074	}
1075	
1076	void
1077	stop_playback (sw_sample * s)
1078	{
1079	  sw_head * head;
1080	
1081	  if (s == NULL) return;
1082	
1083	  head = s->play_head;
1084	
1085	  if (head->going) {
1086	    head_set_going (head, FALSE);
1087	    sample_set_playmarker (s, head->stop_offset, TRUE);
1088	
1089	    g_mutex_lock (play_mutex);
1090	    active_main_heads = g_list_remove (active_main_heads, head);
1091	    g_mutex_unlock (play_mutex);
1092	  }
1093	}
1094	
1095	gboolean
1096	any_playing (void)
1097	{
1098	  return ((player_thread != (pthread_t) -1) && (active_main_heads != NULL));
1099	}
1100	
1101	void
1102	init_playback (void)
1103	{
1104	  play_mutex = g_mutex_new ();
1105	}
11 Jan 2012

Here this is what sweep is

Take the screenshot tour for a visual introduction to Sweep.

The full list of features includes the following:

Extreme ease of use:
Unlimited undo/redo with a fully revertible edit history
Multithreaded background rendering and file import/export: effects processing is not disabled during playback, providing instantaneous feedback.
Precise, interactive scrubbing
Multichannel file support: Sweep provides complete editing and processing for multichannel sound files.
Customisable keybindings available for all operations
Translations for French, Hungarian, Italian, German, Russian and Polish.
Support for many PCM and voice file formats via libsndfile by Erik de Castro Lopo:
at least 14 PCM sound file formats formats including WAV, W64, AIFF/AIFF-C, IFF/SVX, AU and raw PCM files.
PCM audio encoding formats including 8/16/24/32 bit PCM, 32 and 64 bit floating point, u-law, A-law and ADPCM
voice encoding formats including GSM 6.10, G721/G723 ADPCM, 12/16/24 bit DWVW
Support for Ogg Vorbis format audio files:
an exteremely high quality, free, open and unpatented perceptual audio codec.
supports intuitive variable bitrate encoding, where the Vorbis encoder makes low-level encoding decisions.
provides access to average bitrate controls, including bounds on minimum and maximum bitrate usage.
Sweep provides sensible defaults and remembers encoding options between sessions.
Support for Speex files:
a free, open and unpatented speech codec designed for Voice over IP (VoIP) and file-based compression.
supports optional variable bitrate and control over encoding complexity and frame packing.
Sweep provides sensible defaults and remembers encoding options between sessions.
Support for LADSPA effects plugins, including:
the Computer Music Toolkit by Richard Furse, containing high and low pass filters, compressors, delays, and a port of the popular Freeverb reverb unit.
SWH plugins, over 30 effects plugins by Steve Harris, including overdrives, comb filter, ring modulator, pitch scaler, chorus, flanger and various distortions.
more listed at ladspa.org
Powerful editing operations:
Cut, copy and paste insert: conventional cut or copy selected regions of a sound, and paste into the same or other sounds.
Discontinuous selections: select multiple regions of a sound and operate on these regions simultaneously
interactive moving and merging of selection boundaries
Selection invert, selection double/halve and selection shift left/right
Intuitive visualisation:
Multiple views per clip
Variable zooming to below 1:1 with mouse wheel support
View Center, Zoom to Selection, Zoom Normal
Easy differentiation of multiple files with 6 standard colour schemes including Decoder Red, Orangeboom, Coogee Bay Blue and Blackwattle.
Versatile playback modes:
Standard transport features: play/pause, stop, rewind, fast forward, scan reverse/forward, go to end/beginning.
Simultaneous playback of multiple files
Play all, play selection, and looping playback
Interactive reverse playback: includes reverse previews and reverse looping
Flexible recording:
independent record and playback heads
"tape loop" style recording
reverse recording
Device handling and portability:
Support for Open Sound System compatible audio devices (eg. stock Linux kernel), ALSA 0.6.0 and Solaris audio.
Intuitive control of application latency
Support for both little and big endian CPU architectures
Live playback "DJ" features:
Two-handed interactive scrubbing
Independent gain levels per file
+/-10% pitch slider
Piano-style sample playback
11 Jan 2012

And the code I posted where ask if was said right it does work, and it is in the order that you wrote but it did not fix the problem so I thought it could be wrong.

It is is this order but it is in the ticker timer 0

while(1){

 Wait for an audio packet being received 

 Reverse the buffer

 Soften the buffer

 Playback buffer

}

11 Jan 2012

Philips Philips wrote:

And the code I posted where ask if was said right it does work, and it is in the order that you wrote but it did not fix the problem so I thought it could be wrong.

It is is this order but it is in the ticker timer 0

But the ticker is executed for every sample value isn't it ? The softening needs to be done only for the complete packet (so the start and end start at zero level)

11 Jan 2012

Gert van der Knokke wrote:

Philips Philips wrote:

And the code I posted where ask if was said right it does work, and it is in the order that you wrote but it did not fix the problem so I thought it could be wrong.

It is is this order but it is in the ticker timer 0

But the ticker is executed for every sample value isn't it ? The softening needs to be done only for the complete packet (so the start and end start at zero level)

I did not know that is this right Gert?


// Hello World example for the USBMIDI library (circular buffer)

#include "mbed.h"
#include "USBAudio.h"
#include "CircBuffer.h"

Serial pc(USBTX, USBRX);

// frequency: 48 kHz
#define FREQ 32000

// 1 channel: mono
#define NB_CHA 1

// length computed: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
#define LENGTH_AUDIO_PACKET 32 * 2 * 1

#define USR_POWERDOWN    (0x104)

int semihost_powerdown() {
    uint32_t arg;
    return __semihost(USR_POWERDOWN, &arg);
}
 

// USBAudio
USBAudio USBaudio(FREQ, NB_CHA, 0x7186, 0x7507);

// speaker connected to the AnalogOut output. The audio stream received over USb will be sent to the speaker
AnalogOut speaker(p18);

// ticker to send data to the speaker at the good frequency
Ticker tic;

// circular buffer where will be stored data to be sent to the speaker
CircBuffer<int16_t> cbuf(LENGTH_AUDIO_PACKET);

// previous value sent to the speaker
uint16_t p_val = 0;

// function executed each 1/FREQ s
void tic_handler() {
    int16_t val;
    float speaker_value;
    unsigned short PlaySample;


    if (cbuf.available() >= 1) {
        cbuf.dequeue(&val);
        speaker_value = (float)val;

        // speaker_value between 0 and 65535
        speaker_value +=  32768.0;

        // adjust according to current volume
        speaker_value *= USBaudio.getVolume();
    } else {
        speaker_value = p_val;
    }
    p_val = speaker_value;
    
    /* ADAMGR: Inserting my May 30th reversing code here!!! */
  {
    static const unsigned int   BufferSize = 5 * 1024;
    static unsigned short Buffer[BufferSize];
    // int samples[MAX_SAMPLES];
     
     
    static int           Index = 0;
    static int           Direction = 1;
    static int           Playback = false;
    static int           ChunkSize = BufferSize;
    
   // float multiplier = 0.0;
   
 
    unsigned short       ReadSample;
 
    /* Default PlaySample to the current sample from USB buffer. */
    PlaySample =  speaker_value;

    
    
    /* Read out the sample from the buffer to be played back */
    if (Playback)
    {
        PlaySample = Buffer[Index];
    }
    
    /* Obtain current audio sample from the USB buffer. */
    ReadSample = (unsigned short)speaker_value;
    
    /* Record the sample into the buffer right where a space was freed up from the PlaySample read above */
    Buffer[Index] = ReadSample;
    
     /* Increment the buffer pointer */
    Index += Direction;
    
    /* Check to see if the chunk has been filled */
    if (Index < 0)
    {
        /* Now have a chunk to be played back */
        Playback = true;
        /* Reverse the direction of playback and recording */
        Direction *= -1;//Direction;
        Index = 0;
    }
    else if (Index >= ChunkSize)
    
    

    {
       /* Now have a chunk to be played back */
        Playback = true;
        /* Reverse the direction of playback and recording */
        Direction *= -1;//Direction;
        Index = ChunkSize - 1;
   
    
     }
  }
  

    // send value to the speaker
    speaker.write_u16((uint16_t)PlaySample);
}
}
int main() {
    int16_t buf[LENGTH_AUDIO_PACKET/2];
    
    semihost_powerdown();

    // attach a function executed each 1/FREQ s
    tic.attach_us(tic_handler, 1000000.0/(float)FREQ);

    while (1) {
        // read an audio packet
        USBaudio.read((uint8_t *)buf);
        
         int t = 0;
  
  // buffer for our reversed samples (I have used signed int as values)
 int MAX_SAMPLES = 3 * 1024;
int sample[MAX_SAMPLES];
// the multiplier we are going to apply to the sample value
float multiplier=0.0;
  
  MAX_SAMPLES = LENGTH_AUDIO_PACKET/2;
  
  for (t=0; t<512; t++){
    // fade out end samples to zero
    sample[MAX_SAMPLES-t]=sample[MAX_SAMPLES-t]*multiplier;
    // fade in start samples from zero
    sample[t]=sample[t]*multiplier;
    // increment multiplier so we end up at 1 after 10 samples
    multiplier=multiplier+0.1;

        // put buffer in the circ buffer
        for(int i = 0; i < LENGTH_AUDIO_PACKET/2; i++) {
            cbuf.queue(buf[i]);
        }
    }
}
}
12 Jan 2012

Gert,

I am kinda confused now, If 1 packet is received each ms and then unpacked and audio it sent every 31.25 us seconds, how am I supposed to send this 1 packet you talk of after it has the reverse effect applied in real time. when audio is sent and reversed every 31.25 us seconds, that would mean a 1000 cycles.

the way you are suggesting it I would need to delay my speaker output by 1ms, which is 1000us I would like to get not such a long delay if possible.

12 Jan 2012

Philips Philips wrote:

I am kinda confused now, If 1 packet is received each ms and then unpacked and audio it sent every 31.25 us seconds, how am I supposed to send this 1 packet you talk of after it has the reverse effect applied in real time. when audio is sent and reversed every 31.25 us seconds, that would mean a 1000 cycles.

Without some buffering there is no way to know what the next sample value will be (it is realtime) and reversing will never be possible without clicks. Just because it is possible in an audio editor does not mean it is possible in realtime.. The fact you can do realtime scratching on for example a CDJ800 is only possible because it buffers a great deal of the CD track and it also spins at much higher speed than a normal (realtime) CD player. It already knows what samples are coming and also which samples have just been played (they are still in the buffer)

Quote:

the way you are suggesting it I would need to delay my speaker output by 1ms, which is 1000us I would like to get not such a long delay if possible.

Have you tried this already ? I know from audio/video sync problems that anything above 10 ms is quite noticable so maybe 1 ms is not so bad ? Another trick might be that if you are mixing reverse samples and the original sound you need to delay the original sound also so all you can hear are 1 ms delayed samples.

12 Jan 2012

I know us microseconds is possible in sweep and with mbed, but it may need to be in assembly language, 1ms is not bad but I want to get lower if possible.

I think I need 3 timers;) first timer fills up buffer every 31.25us, second timer receives buffer every 31.25us and fills up a buffer and applys effect every 200us, 3 timer receives data from second timer and plays apply effected audio at 31.25us

I think I need help to do this:) I don't know how to transfer the data from timer to timer.

14 Jan 2012

<<quote>>You may put PCM8 data (offset binary) directly to the DAC.<</quote>>

I still think that using 8bits and 8000khz should fix the clicking that would be 125us and only 0.255.

But what do I need to do to the usb audio demo http://mbed.org/handbook/USBAudio I am getting distorted sound at the moment, well sound you can not listen to because it offset. do I just need to make sure that all buffers are int8_t or unsigned 8 ????

Also I wonder for when using 16bit if I will have enough memory and if DMA should be used to transfer the data from the tickers???

15 Jan 2012

It all depends on what kind of audio data you send to the mbed from the PC.

Is it 16 bit or is it 8 bit, is it signed or unsigned is it stereo or mono? Also in what order are 16 bits data received? High byte first or low byte first etc.

Does the example http://mbed.org/users/samux/programs/USBAUDIO_speaker/m1h5sc code work ok ?

15 Jan 2012

Gert van der Knokke wrote:

It all depends on what kind of audio data you send to the mbed from the PC.

Is it 16 bit or is it 8 bit, is it signed or unsigned is it stereo or mono? Also in what order are 16 bits data received? High byte first or low byte first etc.

Does the example http://mbed.org/users/samux/programs/USBAUDIO_speaker/m1h5sc code work ok ?

I don't know what format the audio is because I am trying to watch videos off youtube and listen to radioshure internet radio stream.

But not matter what I chuck at it the usb speaker code works that samux coded http://mbed.org/users/samux/programs/USBAUDIO_speaker/m1h5sc

But when I try to make changes to it to make it work at 8bits it will not work even when I just use the FORMAT_PCM at 8bits, this is what made me try FORMAT_PCM8 but that will not work. You will have to look at the usbdevice libraries

http://mbed.org/users/samux/libraries/USBDevice/m1g6da

as far as I know the usb speaker code output mono

LSB(FORMAT_PCM),                        // wFormatTag
MSB(FORMAT_PCM),                        // wFormatTag

Samuel Mokrani wrote:

The read() function fills an uint8_t array. But these data has to be interpreted as 16 bits signed data (PCM). Then PCM values can be handled according to the number of channels.

I would just use 8bits FORMAT_PCM if I could then it would still be PCM (0x0001) means 2's complementary binary data

instead of PCM8 (0x0002) means offset binary data

But I just want to get 8bits working.

also I see now other way to write to the DAC unsigned 8

<<code>>write Set the output voltage, specified as a percentage (float)<</code>>

<<code>>write_u16 Set the output voltage, represented as an unsigned short in the range [0x0, 0xFFFF<</code>>

15 Jan 2012

Well here I changed USBAudio.cpp

 // Audio Type I Format
        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
        STREAMING_FORMAT_TYPE,                  // bDescriptorSubtype
        FORMAT_TYPE_I,                          // bFormatType
        channel_nb,                             // bNrChannels
        0x01,                                   // bSubFrameSize changed from 0x02 to 0x01
        8,                                     // bBitResolution  changed from 16 to 8
        0x01,                                   // bSamFreqType
        LSB(FREQ),                              // tSamFreq
        (FREQ >> 8) & 0xff,                     // tSamFreq
        (FREQ >> 16) & 0xff,                    // tSamFreq

I Changed main.cpp

int8_t buf[AUDIO_LENGTH_PACKET]; // change from int16_t got rid of /2
//same as above 
uint8_t p_val = 0;

Changed

    speaker.write((uint8_t)PlaySample); // from write.u16 uint16_t

change usbaudio.h

int8_t buf[AUDIO_LENGTH_PACKET];

 for(int i = 0; i < AUDIO_LENGTH_PACKET; i++) {

Not sure if to change here

 */
    virtual void USBCallback_requestCompleted(uint8_t * buf, uint16_t length);

is this right??? what else needs to be changed???

16 Jan 2012

It is right when it sounds right, try taking one step at a time. So first get normal play working then concentrate on the reversal part.

8 bit unsigned (0-255, level zero=128) can be written as 16 bit to the dac after it has been shifted 8 positions to the left (or multiplied by 256)

8 bit signed (-127 to 127, level zero=0) must be converted first (add 128) and then shift 8 positions to the left again.