<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://dsignt.de/support-wiki/index.php?action=history&amp;feed=atom&amp;title=Generate_a_Test_Data_Buffer</id>
	<title>Generate a Test Data Buffer - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://dsignt.de/support-wiki/index.php?action=history&amp;feed=atom&amp;title=Generate_a_Test_Data_Buffer"/>
	<link rel="alternate" type="text/html" href="https://dsignt.de/support-wiki/index.php?title=Generate_a_Test_Data_Buffer&amp;action=history"/>
	<updated>2026-08-14T20:29:27Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.8</generator>
	<entry>
		<id>https://dsignt.de/support-wiki/index.php?title=Generate_a_Test_Data_Buffer&amp;diff=1154&amp;oldid=prev</id>
		<title>WikiImporter: Pushed from DSignT Issue Database.</title>
		<link rel="alternate" type="text/html" href="https://dsignt.de/support-wiki/index.php?title=Generate_a_Test_Data_Buffer&amp;diff=1154&amp;oldid=prev"/>
		<updated>2015-12-08T13:23:50Z</updated>

		<summary type="html">&lt;p&gt;Pushed from DSignT Issue Database.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=== Generate a Buffer with Test Data ===&lt;br /&gt;
&lt;br /&gt;
To debug and test signal processing algorithms it is recommended to use a test data set &lt;br /&gt;
instead of &amp;quot;real world&amp;quot; data acquired by an ADC.&lt;br /&gt;
The following code shows an example to generate a buffer filled with a sine wave.&lt;br /&gt;
The data is truncated to the desired resolution and optionally dithered.&lt;br /&gt;
&lt;br /&gt;
==== Includes ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Defines ====&lt;br /&gt;
The following defines control the signal generation. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define PI 3.1415926535898  /**&amp;lt; pi                                   */&lt;br /&gt;
#define FS_IN 	     44100  /**&amp;lt; input sampling frequency in Hz       */&lt;br /&gt;
#define RES_IN   	16  /**&amp;lt; input resolution in bits             */&lt;br /&gt;
#define SIG_IN        1000  /**&amp;lt; input signal frequency in Hz         */&lt;br /&gt;
#define AMPL_IN      0.995  /**&amp;lt; input signal amplitude (0.0 - 1.0)   */&lt;br /&gt;
#define PHASE_IN    (PI/2)  /**&amp;lt; input signal phase (-pi to pi)       */&lt;br /&gt;
&lt;br /&gt;
#define INBUF_SIZE      32768&lt;br /&gt;
&lt;br /&gt;
#define DITHER_NONE	0    /**&amp;lt; no dither                           */&lt;br /&gt;
#define DITHER_RECT	1    /**&amp;lt; flat spectrum 1/2 LSB	dither        */&lt;br /&gt;
#define DITHER_TRIANGLE	2    /**&amp;lt; high-pass filtered triangular dither*/&lt;br /&gt;
#define DITHER_SHAPED	3    /**&amp;lt; Lipschitz minimal audible dither    */&lt;br /&gt;
&lt;br /&gt;
#define DITHER_TYPE	(DITHER_SHAPED)&lt;br /&gt;
#define DITHERSCALE  	(1.0/((double)RAND_MAX - 0.5))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Buffer ====&lt;br /&gt;
Depending on the selected resolution the generated test data set is stored &lt;br /&gt;
in an int8_t, int16_t or int32_t buffer. Data is always stored left justified, &lt;br /&gt;
i.e. if RES_IN was set to 12, data is stored in a 16-bit buffer with D[15]=MSB, &lt;br /&gt;
D[4] = LSB, and D[3:0] = 0&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#if RES_IN &amp;lt;= 8&lt;br /&gt;
int8_t acqbuf[INBUF_SIZE];&lt;br /&gt;
#elif RES_IN &amp;lt;= 16&lt;br /&gt;
int16_t acqbuf[INBUF_SIZE];&lt;br /&gt;
#else&lt;br /&gt;
int32_t acqbuf[INBUF_SIZE];&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
===== quantisize() =====&lt;br /&gt;
This function quantisizes a normalized double float (range -1.0 to 1.0) to &lt;br /&gt;
the desired integer size and optionally performs dithering&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/*******************************************************************//**&lt;br /&gt;
 @brief     quantisize a normalized double (-1 to +1) to&lt;br /&gt;
            N-bit integer and store in buffer&lt;br /&gt;
&lt;br /&gt;
 @param	    data        - double data&lt;br /&gt;
 @param     bits        - resolution in bits&lt;br /&gt;
 @param     buffer_addr - storage location&lt;br /&gt;
&lt;br /&gt;
 @return    next buffer address&lt;br /&gt;
&lt;br /&gt;
 @note	    requires the following defines:&lt;br /&gt;
 @note	    - DITHER_TYPE (DITHER_NONE, DITHER_RECT,&lt;br /&gt;
              DITHER_TRIANGLE, or DITHER_SHAPED)&lt;br /&gt;
&lt;br /&gt;
***********************************************************************/&lt;br /&gt;
uint32_t quantisize (double data, uint32_t bits, uint32_t buffer_addr)&lt;br /&gt;
{&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      locals&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    double scale;&lt;br /&gt;
    uint32_t addr = buffer_addr;&lt;br /&gt;
&lt;br /&gt;
#if DITHER_TYPE != DITHER_NONE&lt;br /&gt;
    double r;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if DITHER_TYPE == DITHER_TRIANGLE&lt;br /&gt;
    static double dither_last = 0.0;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if DITHER_TYPE == DITHER_SHAPED&lt;br /&gt;
    /* Lipshitz&amp;#039;s minimally audible FIR */&lt;br /&gt;
    static double dither_coeff[5]  = {2.033, -2.165, 1.959, -1.590, 0.6149};&lt;br /&gt;
    static double dither_buffer[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};&lt;br /&gt;
    static uint32_t dither_phase = 0;&lt;br /&gt;
    uint32_t idx;&lt;br /&gt;
    double x;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      scale data&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    scale = pow(2.0, (double)(bits-1)) - 2.0;&lt;br /&gt;
    data = data * scale;&lt;br /&gt;
&lt;br /&gt;
#if DITHER_TYPE == DITHER_NONE&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      round to nearest integer&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    data = floor (data + 0.5);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (DITHER_TYPE == DITHER_RECT)&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      add dither and round to nearest integer&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    r = (double)rand() * DITHERSCALE;&lt;br /&gt;
    data = floor (data + r + 0.5);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if (DITHER_TYPE == DITHER_TRIANGLE)&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      add high-pass filtered dither and round to nearest integer&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    r = (double)rand() * DITHERSCALE;&lt;br /&gt;
    data = floor (data + r - dither_last + 0.5);&lt;br /&gt;
    dither_last = r;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if DITHER_TYPE == DITHER_SHAPED&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      dither noise shaping in FIR filter&lt;br /&gt;
      add noise shaped + triangular dither&lt;br /&gt;
      store last error and roll buffer&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    x = data;&lt;br /&gt;
    for (idx = 0; idx &amp;lt; 5; idx++)&lt;br /&gt;
    {&lt;br /&gt;
	x = x + dither_buffer[(dither_phase - idx) &amp;amp; 7] * dither_coeff[idx];&lt;br /&gt;
    }&lt;br /&gt;
    r = (double)rand() * DITHERSCALE;&lt;br /&gt;
    r += (double)rand() * DITHERSCALE;&lt;br /&gt;
    data = x + r;&lt;br /&gt;
&lt;br /&gt;
    dither_phase++;&lt;br /&gt;
    dither_phase &amp;amp;= 7;&lt;br /&gt;
    data = floor (data + 0.5);&lt;br /&gt;
    dither_buffer[dither_phase] = x - data;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      saturate&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    if (data &amp;gt; scale) data = scale;&lt;br /&gt;
    if (data &amp;lt; -scale) data = -scale;&lt;br /&gt;
&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      store in buffer&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    if (bits &amp;lt;= 8)&lt;br /&gt;
    {&lt;br /&gt;
        *(int8_t *)addr = (int8_t)data &amp;lt;&amp;lt; (8-bits);&lt;br /&gt;
        addr += 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (bits &amp;lt;= 16)&lt;br /&gt;
    {&lt;br /&gt;
        *(int16_t *)addr = (int16_t)data &amp;lt;&amp;lt; (16-bits);&lt;br /&gt;
        addr +=2;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *(int32_t *)addr = (int32_t)data &amp;lt;&amp;lt; (32-bits);&lt;br /&gt;
        addr += 4;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      update address&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    return addr;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Sinewave Generator =====&lt;br /&gt;
generate a sinewave, calls quantisize&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/*******************************************************************//**&lt;br /&gt;
 @brief     generate a sinewave signal&lt;br /&gt;
&lt;br /&gt;
 @param	    fs - sampling frequency in Hz&lt;br /&gt;
 @param	    fsig - signal frequency in Hz&lt;br /&gt;
 @param	    asig - signal amplitude (0.0 to 1.0)&lt;br /&gt;
 @param	    psig - signal phase (-pi to pi)&lt;br /&gt;
 @param     bits - signal resolution in bits&lt;br /&gt;
 @param	    buffer - pointer to buffer memory&lt;br /&gt;
 @param	    buffersize - size of buffer in samples&lt;br /&gt;
&lt;br /&gt;
 @note	    output array is left justified&lt;br /&gt;
 @note      calls quantisize()&lt;br /&gt;
&lt;br /&gt;
***********************************************************************/&lt;br /&gt;
void sinegen ( uint32_t fs, double fsig, double asig, double psig, uint32_t bits, void* buffer, uint32_t buffersize)&lt;br /&gt;
{&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      locals&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    double arg;&lt;br /&gt;
    double tmp;&lt;br /&gt;
    uint32_t idx;&lt;br /&gt;
    uint32_t addr = (uint32_t)buffer;&lt;br /&gt;
&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      calculate argument&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    arg = 2.0 * PI * fsig / (double)fs;&lt;br /&gt;
&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      calculate sinewave&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    for (idx = 0; idx &amp;lt; buffersize; idx++)&lt;br /&gt;
    {&lt;br /&gt;
	tmp = asig * sin (arg * (double)idx  + psig);&lt;br /&gt;
	addr = quantisize (tmp, bits, addr);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Example =====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/***********************************************************************&lt;br /&gt;
&lt;br /&gt;
  MAIN PROGRAM&lt;br /&gt;
&lt;br /&gt;
***********************************************************************/&lt;br /&gt;
void main (void)&lt;br /&gt;
{&lt;br /&gt;
    /*******************************************************************&lt;br /&gt;
      generate acquisition sample buffer&lt;br /&gt;
    *******************************************************************/&lt;br /&gt;
    sinegen (FS_IN, SIG_IN, AMPL_IN, PHASE_IN, RES_IN, acqbuf, INBUF_SIZE);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Dither Modes ====&lt;br /&gt;
The following spectrum plots show the effect of dithering:&lt;br /&gt;
[[File:16bit_no_dither.png]]&lt;br /&gt;
[[File:16bit_rectangular_dither.png]]&lt;br /&gt;
[[File:16bit_triangular_hp_dither.png]]&lt;br /&gt;
[[File:16bit_shaped_dither.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{pagetop}}&lt;br /&gt;
&lt;br /&gt;
== Additional Tags ==&lt;br /&gt;
Sinewave Dither Noiseshaping&lt;br /&gt;
&lt;br /&gt;
 [[category:Software]][[category:DSP]]&lt;/div&gt;</summary>
		<author><name>WikiImporter</name></author>
	</entry>
</feed>