remstart
Globals required:

dim signal() as SINUSOIDAL_WAVE
dim fftreal(1) as float
dim fftimag(1) as float
dim histogram(1) as integer
dim fftstage() as integer
dim spectrum_analysis() as FREQUENCY_DATA
dim waves() as WAVEOBJECT

remend

#constant MAX_VOLUME = 32767.0
#constant WAVE_FORMAT_PCM = 1
#constant SIZEOF_winWAVEFORMATEX = 18
#constant SIZEOF_dbWAVEFORMATEX = 28

remstart
    DBPro aligns the WAVEFORMATEX structure on DWORD boundaries, so the image in
    memory is not directly interchangeable with a RAW wavefile. In addition, RAW
    wavefiles use a format called RIFF, as does MIDI. See the functions for RAW
    wavefile loading and saving for implementation details.
remend

#constant _WFORMAT          = 0
#constant _NCHANNELS        = 4
#constant _NSAMPLESPERSEC   = 8
#constant _NAVGBYTESPERSEC  = 12
#constant _NBLOCKALIGN      = 16
#constant _WBITSPERSAMPLE   = 20
#constant _CBSIZE           = 24

rem Wave types. Use these to tell the code how to generate a wave.

#constant SINEWAVE          = 0
#constant SQUAREWAVE        = 1
#constant SAWTOOTHWAVE      = 2
#constant TRIANGLEWAVE      = 3
#constant ADSR              = 4
#constant OTHER_FUNCTION    = 5
#constant NOISE             = 0xffff0000
#constant SAVE_FILE         = 0xfffffffe
#constant LOAD_FILE         = 0xffffffff

#constant MACH_1_0E70F      = 1128.0

type winWAVEFORMATEX
    wFormat                 as word
    nChannels               as word
    nSamplesPerSec          as dword
    nAvgBytesPerSec         as dword
    nBlockAlign             as word
    wBitsPerSample          as word
    cbSize                  as word
endtype

type dbWAVEFORMATEX
    wFormat                 as dword
    nChannels               as dword
    nSamplesPerSec          as dword
    nAvgBytesPerSec         as dword
    nBlockAlign             as dword
    wBitsPerSample          as dword
    cbSize                  as dword
endtype

type FREQUENCY_DATA
    frequency       as float
    amplitude       as float
    phase           as float
endtype

type DFTPAIR
    cosAmplitude    as float
    sinAmplitude    as float
endtype

type JZWAVEOBJECT
    filename        as string
    soundnumber     as integer
    timedata        as JZMEMORY
    frequencydata   as JZMEMORY
    interpolated    as JZMEMORY
    decimated       as JZMEMORY
    mean            as float
    stddeviation    as float
    snr             as float
    rms             as float
    bias            as float
endtype

type CREATEWAVE
    wavetype        as integer
    wavespec        as FREQUENCY_DATA
endtype

type SINUSOIDAL_WAVE
    fundamental as float            rem Frequency
    theta       as float            rem Instantaneous angle
    delta       as float            rem Incremental rotation
    amplitude   as float            rem Peak amplitude
endtype

#constant SINGLEENDED           = 0x00000000
#constant DOUBLEENDED           = 0x00000001
#constant TIMEDOMAINDATA        = 0x00000002
#constant FREQUENCYDOMAINDATA   = 0x00000004
#constant BITS_8                = 0x00000008
#constant BITS_16               = 0x00000010
#constant BITS_24               = 0x00000018
#constant BITS_32               = 0x00000020
#constant BITS_64               = 0x00000040
#constant RAW_DATA              = 0x00000080
#constant FILTER_DATA           = 0x00000100
#constant SHOW_REAL             = 0x00000200
#constant SHOW_IMAG             = 0x00000400
#constant FFT_ANALYSIS          = 0x00000800
#constant UNBINNED_HISTOGRAM    = 0x00001000
#constant BINNED_HISTOGRAM      = 0x00002000
#constant DRAW_INTERSAMPLE      = 0x80000000
#constant DRAW_IMPULSE          = 0x40000000

type JZPOINT
    x                   as integer
    y                   as integer
endtype

type JZRECT
    top                 as integer
    left                as integer
    bottom              as integer
    right               as integer
endtype

type JZGRAPH
    name                as string
    rect                as JZRECT
    zeroline            as integer
    x_scale             as integer
    y_scale             as float
    color               as dword
    background          as dword
    datasize            as integer
    memblock            as integer
    offset              as integer
    start               as integer
    stop                as integer
    cursor              as integer
    mark1               as integer
    mark2               as integer
    min                 as integer
    max                 as integer
    hMarks              as integer
    vMarks              as integer
    graphflags          as dword
    ftemp               as float
endtype

global x1 as integer
global x2 as integer
global y1 as integer
global y2 as integer

function GenerateSignal16(ptr as dword, numsamples as integer)
    local integrator as integer = 0
    local i as integer
    local j as integer
    local wtemp as word

    for i = 0 to numsamples - 1
        integrator = 0
        for j = 0 to array count(signal())
            inc integrator, int(sin(wrapvalue(signal(j).theta)) * ...
                                signal(j).amplitude)
            inc signal(j).theta, signal(j).delta
        next j
        wtemp = integrator
        *ptr = wtemp
        inc ptr, 2
    next i
endfunction

function WritePCMWaveFile(filename as string, wavedata_blk as integer, ...
                          size as integer)
    local i as integer
    local j as integer
    local k as integer
    local s2 as integer
    local ptr as dword

    ptr = get memblock ptr(wavedata_blk)
    s2 = size << 1
    if file exist(filename)
        delete file filename
    endif
    open to write 1, filename
    write byte 1, asc("R")
    write byte 1, asc("I")
    write byte 1, asc("F")
    write byte 1, asc("F")
    write long 1, s2 + 42
    write byte 1, asc("W")
    write byte 1, asc("A")
    write byte 1, asc("V")
    write byte 1, asc("E")
    write byte 1, asc("f")
    write byte 1, asc("m")
    write byte 1, asc("t")
    write byte 1, asc(" ")
    write long 1, 16
    write word 1, *ptr
    inc ptr, 4
    write word 1, *ptr
    inc ptr, 4
    write long 1, *ptr
    inc ptr, 4
    write long 1, *ptr
    inc ptr, 4
    write word 1, *ptr
    inc ptr, 4
    write word 1, *ptr
    inc ptr, 4
    write byte 1, asc("d")
    write byte 1, asc("a")
    write byte 1, asc("t")
    write byte 1, asc("a")
    write long 1, s2

    for k = 0 to size - 1
        write word 1, *ptr
        inc ptr, 2
    next k
    close file 1
endfunction

function MakeSpectrumBand(frequency as float)
    array insert at bottom spectrum_analysis()
    spectrum_analysis().frequency = frequency
    spectrum_analysis().amplitude = 0.0
    spectrum_analysis().phase = 0.0
endfunction

function DoDFTSpectrumAnalysis(block as integer, pad as boolean)
    local i as integer
    local j as integer
    local x as integer
    local start as integer = 0
    local enddata as integer = 0
    local dataptr as dword
    local datum as word
    local datavalue as float
    local numSamples as integer
    local referenceAngle as float
    local refAngleStart as float
    local real as float
    local imag as float
    local tempreal as float
    local tempimag as float
    local realfrequency as float
    local stupidfloat as float

    start = SIZEOF_dbWAVEFORMATEX
    numSamples = get memblock size(block) - start
    numSamples = numSamples / memblock dword(block, _NBLOCKALIGN)
    enddata = numSamples - 1
    if pad = TRUE
        numSamples = 1.0 * memblock dword(block, _NSAMPLESPERSEC)
    endif
    for i = 0 to array count(spectrum_analysis())
        real = 0.0
        imag = 0.0
        dataptr = get memblock ptr(block)
        inc dataptr, start
        refAngleStart = twopi * spectrum_analysis(i).frequency
        for x = 0 to numSamples - 1
            stupidfloat = 1.0 * x
            stupidfloat = stupidfloat / (1.0 * numSamples)
            if x < enddata
                datum = *dataptr
                datavalue = jzMakeWordIntValue(datum) * 1.0
            else
                datavalue = 0.0
            endif
            referenceAngle = refAngleStart * stupidfloat
            referenceAngle = referenceAngle * radian_convert
            tempreal = datavalue * cos(referenceAngle)
            tempimag = datavalue * sin(referenceAngle)
            inc real, tempreal
            dec imag, tempimag
            inc dataptr, 2
        next x
        stupidfloat = sqrt((imag * imag) + (real * real))
        stupidfloat = stupidfloat / MAX_VOLUME
        stupidfloat = 100.0 * stupidfloat
        spectrum_analysis(i).amplitude = stupidfloat
        stupidfloat = atan(imag / real)
        spectrum_analysis(i).phase = stupidfloat
        remstart
        if pad = FALSE
            realfrequency = 1.0 * numSamples
            realfrequency = realfrequency / 2.0
            inc realfrequency, 1.0
            realfrequency = realfrequency / (1.0 * array count(spectrum_analysis()))
            realfrequency = realfrequency * (1.0 * i)
            spectrum_analysis(i).frequency = realfrequency
        endif
        remend
    next i
endfunction

function DoWaveFileFFT16(wavenumber as integer, start as integer, ...
                         length as integer)
    local numbytes as integer = 0
    local numsamples as integer
    local source as integer = 0
    local srcoffset as integer = 0
    local dest as integer = 0
    local i as integer = 0
    local ie as integer = 0
    local ie2 as integer = 0
    local ip as integer = 0
    local j as integer = 0
    local jm1 as integer = 0
    local k as integer = 0
    local nm1 as integer = 0
    local nd2 as integer = 0
    local nd2m1 as integer = 0
    local N as integer = 0
    local ur as float = 0.0
    local ui as float = 0.0
    local sr as float = 0.0
    local si as float = 0.0
    local tr as float = 0.0
    local ti as float = 0.0
    local stages as integer = 0
    local offset as integer = 0
    local wtemp as word = 0

    source = waves(wavenumber).timedata.memblockID
    numbytes = get memblock size(source)
    numsamples = numbytes - start
    numsamples = numsamples >> 1
    stages = jzGetMaxPowerof2(length)
    N = jzPow2(stages)
    nm1 = N - 1
    nd2 = N >> 1
    nd2m1 = nd2 - 1
    k = N << 1
    if waves(wavenumber).frequencydata.memblockID > 0
        if memblock exist(waves(wavenumber).frequencydata.memblockID)
            delete memblock waves(wavenumber).frequencydata.memblockID
        endif
    endif
    waves(wavenumber).frequencydata.memblockID = ...
        jzGetNextAvailableMemblockID(1)
    make memblock waves(wavenumber).frequencydata.memblockID, k
    waves(wavenumber).frequencydata.ptr = ...
        get memblock ptr(waves(wavenumber).frequencydata.memblockID)
    fill memory waves(wavenumber).frequencydata.ptr, 0x00, k
    dest = waves(wavenumber).frequencydata.memblockID

    rem Clear out arrays and redimension those that require it.

    empty array fftstage()
    undim fftreal()
    undim fftimag()
    dim fftreal(N)
    dim fftimag(N)

remstart    Find out the stage values for the sort. (N/2, N/4, N/8, etc.)
            Stage 0 is actually N, but the algorithm is better using 1 - N
            at the frequency domain synthesis portion of the routine.
remend

    for i = 0 to stages - 1
        array insert at bottom fftstage()
        if i = 0
            fftstage() = 0
        else
            fftstage() = N / jzPow2(i)
        endif
    next i

remstart    The real secret of the FFT algorithm is the bit reversal sort,
            which moves the data from the time domain to the frequency domain
            by reordering the samples. The new order is bit reversed from the
            original. This is accomplished by brute force in many of the samples
            I have examined. It is also a favorite topic of programmers that are
            fans of recursive programming. I always try my best to avoid using
            recursion. I think that it is better to work a little longer on a
            routine and come up with a better solution. In this case it really
            paid off; I have a very fast routine that reorders a copy of the data
            and does an FFT on it. This is the basis of any number of audio DSP
            applications.
remend

    for i = 0 to nd2m1
        j = i << 1
        offset = fftstage(0)
        if i && 0x00000001
            inc offset, fftstage(1)
        endif
        if i && 0x00000002
            inc offset, fftstage(2)
        endif
        if i && 0x00000004
            inc offset, fftstage(3)
        endif
        if i && 0x00000008
            inc offset, fftstage(4)
        endif
        if i && 0x00000010
            inc offset, fftstage(5)
        endif
        if i && 0x00000020
            inc offset, fftstage(6)
        endif
        if i && 0x00000040
            inc offset, fftstage(7)
        endif
        if i && 0x00000080
            inc offset, fftstage(8)
        endif
         if i && 0x00000100
            inc offset, fftstage(9)
        endif
        if i && 0x00000200
            inc offset, fftstage(10)
        endif
        if i && 0x00000400
            inc offset, fftstage(11)
        endif
        if i && 0x00000800
            inc offset, fftstage(12)
        endif
        if i && 0x00001000
            inc offset, fftstage(13)
        endif
        if i && 0x00002000
            inc offset, fftstage(14)
        endif
        if i && 0x00004000              rem 65536 samples per second
            inc offset, fftstage(15)
        endif
        if i && 0x00008000
            inc offset, fftstage(16)
        endif
        fftimag(i) = 0.0
        fftimag(nd2 + i) = 0.0
        if offset < numsamples
            offset = offset << 1
            srcoffset = start + offset
            fftreal(i) = ...
                1.0 * jzMakeWordIntValue(memblock word(source, srcoffset))
            fftreal(nd2 + i) = ...
                1.0 * jzMakeWordIntValue(memblock word(source, srcoffset + 2))
            write memblock word dest, j, memblock word(source, srcoffset)
            write memblock word dest, N + j, ...
                                memblock word(source, srcoffset + 2)
        else
            fftreal(i) = 0.0
            fftreal(nd2 + i) = 0.0
            write memblock word dest, j, 0x0000
            write memblock word dest, N + j, 0x0000
        endif
    next i

remstart    The FFT algorithm works like many of the traditional filters used
            in audio applications (analog, as well as digital) by using stages.
            In some filters, the term pole is used. The DFT and other routines
            gather power and phase information by running through the entire
            dataset many times. The FFT does not work that way, however. After
            reordering the data set, it is no longer necessary to use each
            sample every time. The routine is controlled completely by the
            length of the dataset and the properties of the FFT algorithm.
remend

    for i = 1 to stages
        ie = jzPow2(i)
        ie2 = ie >> 1
        ui = (pi / (1.0 * ie2)) * radian_convert
        sr = cos(ui)
        si = sin(ui)
        ur = 1.0
        ui = 0.0
        for j = 1 to ie2
            jm1 = j - 1
            for k = jm1 to nm1 step ie
                ip = k + ie2
                tr = ur * fftreal(ip) - ui * fftimag(ip)
                ti = ui * fftreal(ip) + ur * fftimag(ip)
                fftreal(ip) = fftreal(k) - tr
                fftimag(ip) = fftimag(k) - ti
                fftreal(k) = fftreal(k) + tr
                fftimag(k) = fftimag(k) + ti
            next k
            tr = ur
            ur = tr * sr - ui * si
            ui = tr * si + ui * sr
        next j
    next i
endfunction

function CreateWaveFromFile(name as string)
    local iReturn as integer = -1

    array insert at bottom waves()
    waves().filename = name
    waves().soundnumber = jzGetNextAvailableSoundID(1)
    load sound waves().filename, waves().soundnumber
    waves().timedata.memblockID = jzGetNextAvailableMemblockID(1)
    make memblock from sound waves().timedata.memblockID, ...
                             waves().soundnumber
    waves(currentwave).timedata.ptr = ...
        get memblock ptr(waves().timedata.memblockID)
    waves().frequencydata.memblockID = 0
    waves().frequencydata.ptr = NULL
    waves().interpolated.memblockID = 0
    waves().interpolated.ptr = NULL
    waves().decimated.memblockID = 0
    waves().decimated.ptr = NULL
    waves().mean = 0.0
    waves().stddeviation = 0.0
    waves().snr = 0.0
    waves().rms = 0.0
    waves().bias = 0.0
    iReturn = array count(waves())
    GetWaveStatistics(iReturn)
endfunction iReturn

function GetWaveSampleTime(wave as integer, samplenumber as integer)
    local sampletime as float = 0.0

    if wave <= array count(waves())
        sampletime = 1.0 * memblock word(waves(wave).timedata.memblockID, ...
                                         _NSAMPLESPERSEC)
        if samplenumber > 0
            sampletime = 1.0 * samplenumber / sampletime
        endif
    endif
endfunction sampletime

function GetWaveStatistics(wave as integer)
    local i as integer = 0
    local j as integer = 0
    local ptr as dword = 0
    local numsamples as integer = 0
    local total as float = 0.0
    local totalexcursion as float = 0.0
    local ftemp as float = 0.0
    local ftemp2 as float = 0.0
    local variance as float = 0.0

    if wave <= array count(waves())
        numsamples = get memblock size(waves(wave).timedata.memblockID) - ...
                     SIZEOF_dbWAVEFORMATEX
        numsamples = numsamples >> 1
        ptr = waves(wave).timedata.ptr
        inc ptr, SIZEOF_dbWAVEFORMATEX
        for i = 0 to numsamples - 1
            ftemp = 1.0 * jzMakeWordIntValue(*ptr)
            inc totalexcursion, ftemp
            inc total, abs(ftemp)
            inc ptr, 2
        next i
        ftemp2 = 1.0 * numsamples
        ftemp = total / ftemp2
        waves(wave).mean = ftemp
        ftemp = totalexcursion / ftemp2
        waves(wave).bias = ftemp
        variance = 0.0
        ptr = waves(wave).timedata.ptr
        inc ptr, SIZEOF_dbWAVEFORMATEX
        for i = 0 to numsamples - 1
            ftemp = 1.0 * abs(jzMakeWordIntValue(*ptr))
            dec ftemp, waves(wave).mean
            inc variance, ftemp * ftemp
            inc ptr, 2
        next i
        dec ftemp2, 1.0
        variance = variance / ftemp2
        waves(wave).stddeviation = sqrt(variance)
        waves(wave).snr = waves(wave).mean / waves(wave).stddeviation

        undim histogram()
        dim histogram(jzPow2(16))
        for i = 0 to jzPow2(16) - 1
            histogram(i) = 0
        next i
        j = 0
        for i = 0 to numsamples - 1
            inc histogram(memblock word(waves(wave).timedata.memblockID, j)), 1
            inc j, 2
        next i
        j = 0
        for i = 0 to jzPow2(16) - 1
            if histogram(i) <> 0
                inc j, 1
            endif
        next i
    endif
endfunction

function GetMaxHistogramBinValue()
    local i as integer = 0
    local j as integer = 0

    for i = 0 to array count(histogram()) - 1
        if histogram(i) > j
            j = histogram(i)
        endif
    next i
endfunction j

function DecimateWave(wave as integer, newrate as integer)
    rem
endfunction

function InterpolateWave(wave as integer, newrate as integer)
    rem
endfunction

function MixWaves(wave1 as integer, wave2 as integer, ratio as float, ...
                  method as integer)
    local iReturn as integer = -1

    array insert at bottom waves()
    waves().filename = "tempmix.wav"
    waves().soundnumber = -1
    waves().timedata.memblockID = -1
    waves(currentwave).timedata.ptr = NULL
    waves().frequencydata.memblockID = 0
    waves().frequencydata.ptr = NULL
    waves().interpolated.memblockID = 0
    waves().interpolated.ptr = NULL
    waves().decimated.memblockID = 0
    waves().decimated.ptr = NULL
    waves().mean = 0.0
    waves().stddeviation = 0.0
    waves().snr = 0.0
    waves().rms = 0.0
    waves().bias = 0.0
    iReturn = array count(waves())


    rem GetWaveStatistics(iReturn)
endfunction iReturn

function GetSamplesPerBaud(sps as integer, bps as integer)
    local samples as float
    local baud as float
    local samplesperbaud as float
    local ireturn as integer

    samples = 1.0 * sps
    baud = 1.0 * bps
    samplesperbaud = samples / baud
    ireturn = int(samplesperbaud)
endfunction ireturn

function DSPShutdown()
    local i as integer

    for i = 0 to array count(waves())
        if waves(i).timedata.memblockID > 0
            if memblock exist(waves(i).timedata.memblockID)
                delete memblock waves(i).timedata.memblockID
            endif
        endif
        if waves(i).frequencydata.memblockID > 0
            if memblock exist(waves(i).frequencydata.memblockID)
                delete memblock waves(i).frequencydata.memblockID
            endif
        endif
        if waves(i).interpolated.memblockID > 0
            if memblock exist(waves(i).interpolated.memblockID)
                delete memblock waves(i).interpolated.memblockID
            endif
        endif
        if waves(i).decimated.memblockID > 0
            if memblock exist(waves(i).decimated.memblockID)
                delete memblock waves(i).decimated.memblockID
            endif
        endif
        if sound exist(waves(i).soundnumber)
            delete sound waves(i).soundnumber
        endif
    next i
    empty array waves()
    empty array spectrum_analysis()
endfunction

function GetMaxYScale(value as integer, numpixels as integer)
    local maxscale as float
    local ival as float
    local inumpixels as float

    ival = 1.0 * value
    inumpixels = 1.0 * numpixels
    if inumpixels > ival
        maxscale = inumpixels / ival
    else
        maxscale = 1.0 / (ival / inumpixels)
    endif
endfunction maxscale

function GetGraphCursorTime(graph as integer)
    local timef as float = 0.0

    if graph <= array count(graphs())
        timef = GetWaveSampleTime(0, (graphs(graph).cursor - ...
                                  graphs(graph).start) >> 1)
    endif
endfunction timef

function PlotNextGraphPage(graph as integer)

    if graph <= array count(graphs())
        graphs(graph).offset = PlotGraph(graph)
    endif
endfunction

function PlotPreviousGraphPage(graph as integer)

    if graph <= array count(graphs())
        if graphs(graph).offset < screen_width * 4
            graphs(graph).offset = graphs(graph).start
        else
            graphs(graph).offset = graphs(graph).offset - screen_width * 4
        endif
        graphs(graph).offset = PlotGraph(graph)
    endif
endfunction

function ToggleGraphState(graph as integer, state as dword)

    if graph <= array count(graphs())
        graphs(graph).graphflags = graphs(graph).graphflags ~~ state
        i = PlotGraph(graph)
    endif
endfunction

function IncrementGraphCursorPosition(graph as integer)
    local i as integer

    if graph <= array count(graphs())
        inc graphs(graph).cursor, graphs(graph).datasize
        if graphs(graph).cursor > graphs(graph).stop
            graphs(graph).cursor = graphs(graph).stop
        endif
        i = PlotGraph(graph)
    endif
endfunction

function DecrementGraphCursorPosition(graph as integer)
    local i as integer

    if graph <= array count(graphs())
        dec graphs(graph).cursor, graphs(graph).datasize
        if graphs(graph).cursor < graphs(graph).start
            graphs(graph).cursor = graphs(graph).start
        endif
        i = PlotGraph(graph)
    endif
endfunction

function IncrementGraphXScale(graph as integer)

    if graph <= array count(graphs())
        inc graphs(graph).x_scale, 1
        if graphs(graph).x_scale >= mid_x
            graphs(graph).x_scale = mid_x
        endif
        i = PlotGraph(graph)
    endif
endfunction

function DecrementGraphXScale(graph as integer)

    if graph <= array count(graphs())
        dec graphs(graph).x_scale, 1
        if graphs(graph).x_scale < 1
            graphs(graph).x_scale = 1
        endif
        i = PlotGraph(graph)
    endif
endfunction

function PointInRect(pt as JZPOINT, graph as integer)
    local inrect as boolean

    if graph <= array count(graphs())
        inrect = FALSE
        if pt.x >= graphs(graph).rect.left and ...
           pt.x <= graphs(graph).rect.right and ...
           pt.y >= graphs(graph).rect.top and ...
           pt.y <= graphs(graph).rect.bottom
            inrect = TRUE
        endif
    endif
endfunction inrect

function PlotGraph(plotgraph as integer)
    local x1 as integer
    local x2 as integer
    local y1 as integer
    local y2 as integer
    local offset as integer
    local linesize as integer = 2
    local samplecolor as dword = 0x00000000
    local ptr as dword
    local datum as word
    local datavalue as float
    local i as integer

    if plotgraph <= array count(graphs())
        ink graphs(plotgraph).background, 0
        box graphs(plotgraph).rect.left, graphs(plotgraph).rect.top, ...
            graphs(plotgraph).rect.right, graphs(plotgraph).rect.bottom
        x1 = graphs(plotgraph).rect.left
        y1 = graphs(plotgraph).zeroline
        ink rgb(255, 255, 255), 0
        set cursor graphs(plotgraph).rect.left, graphs(plotgraph).rect.top
        print graphs(plotgraph).name
        line x1, graphs(plotgraph).zeroline, graphs(plotgraph).rect.right, y1
        ink rgb(192, 192, 192), 0
        line graphs(plotgraph).rect.left, graphs(plotgraph).rect.top, ...
             graphs(plotgraph).rect.right, graphs(plotgraph).rect.top
        line graphs(plotgraph).rect.left, graphs(plotgraph).rect.bottom, ...
             graphs(plotgraph).rect.right, graphs(plotgraph).rect.bottom
        ink graphs(plotgraph).color, 0
        if graphs(plotgraph).graphflags && DOUBLEENDED
            x1 = graphs(plotgraph).rect.left
            y1 = graphs(plotgraph).zeroline
            offset = graphs(plotgraph).offset
            if graphs(plotgraph).memblock > 0
                ptr = get memblock ptr(graphs(plotgraph).memblock)
                if offset >= graphs(plotgraph).stop
                    dec offset, graphs(plotgraph).datasize
                endif
                inc ptr, offset
                datum = *ptr
                datavalue = 1.0 * jzMakeWordIntValue(datum)
                dec y1, datavalue * graphs(plotgraph).y_scale
                inc ptr, graphs(plotgraph).datasize
            endif
            for i = graphs(plotgraph).rect.left to graphs(plotgraph).rect.right step graphs(plotgraph).x_scale
                if graphs(plotgraph).graphflags && RAW_DATA
                    if offset >= graphs(plotgraph).stop
                        datavalue = 0.0
                    else
                        datum = *ptr
                        datavalue = 1.0 * jzMakeWordIntValue(datum)
                        if offset = graphs(plotgraph).cursor
                            samplecolor = rgb(255, 255, 0)
                            linesize = 4
                        endif
                        inc offset, graphs(plotgraph).datasize
                        inc ptr, graphs(plotgraph).datasize
                    endif
                endif
                x2 = x1 + graphs(plotgraph).x_scale
                y2 = graphs(plotgraph).zeroline - (datavalue * graphs(plotgraph).y_scale)
                if graphs(plotgraph).graphflags && DRAW_INTERSAMPLE
                    line x1, y1, x2, y2
                endif
                if graphs(plotgraph).graphflags && DRAW_IMPULSE
                    ink rgb(0, 255, 0), 0
                    line x2, graphs(plotgraph).zeroline, x2, y2
                endif
                ink samplecolor, 0
                line x2 - linesize, y2, x2 + linesize, y2
                line x2, y2 - linesize, x2, y2 + linesize
                if linesize = 4
                    circle x2, y2, 6
                endif
                samplecolor = 0x00000000
                linesize = 2
                x1 = x2
                y1 = y2
                ink graphs(plotgraph).color, 0
            next i
            if offset >= graphs(plotgraph).stop
                offset = graphs(plotgraph).start
            endif
            ink rgb(255, 255, 255), 0
            print "Mean: " + str$(waves(0).mean, 3) + ...
                  " | stddev: " + str$(waves(0).stddeviation, 3) + ...
                  " | SNR: " + str$(waves(0).snr, 3) + " : 1" + " | bias: " + ...
                  str$(waves(0).bias, 3) + " | sample#: " + ...
                  str$((graphs(plotgraph).cursor - SIZEOF_dbWAVEFORMATEX) >> 1) + ...
                  " | time: " + str$(GetGraphCursorTime(plotgraph), 6)
        else
            if graphs(plotgraph).graphflags && FREQUENCYDOMAINDATA
                if graphs(plotgraph).graphflags && SHOW_REAL
                    for i = graphs(plotgraph).start to graphs(plotgraph).stop
                        x2 = x1 + graphs(plotgraph).x_scale
                        y2 = graphs(plotgraph).zeroline - ...
                        (spectrum_analysis(i).amplitude * graphs(plotgraph).y_scale)
                        line x1, y1, x2, y2
                        x1 = x2
                        y1 = y2
                    next i
                else
                    if graphs(plotgraph).graphflags && SHOW_IMAG
                        for i = graphs(plotgraph).start to graphs(plotgraph).stop
                            x2 = x1 + graphs(plotgraph).x_scale
                            y2 = graphs(plotgraph).zeroline + ...
                            (spectrum_analysis(i).phase * graphs(plotgraph).y_scale)
                            line x1, y1, x2, y2
                            x1 = x2
                            y1 = y2
                        next i
                    endif
                endif
                print "DC Bias:" + str$(spectrum_analysis(0).amplitude, 3)
            else
                if graphs(plotgraph).graphflags && FFT_ANALYSIS
                    for i = graphs(plotgraph).start to graphs(plotgraph).stop
                        x2 = x1 + graphs(plotgraph).x_scale
                        datavalue = 2.0 * ...
                            sqrt((fftreal(i) * fftreal(i)) + ...
                                (fftimag(i) * fftimag(i)))
                        datavalue = datavalue / MAX_VOLUME
                        datavalue = datavalue * 100.0
                        y2 = graphs(plotgraph).zeroline - ...
                            (datavalue * graphs(plotgraph).y_scale)
                        line x1, y1, x2, y2
                        x1 = x2
                        y1 = y2
                    next i
                    datavalue = 2.0 * ...
                        sqrt((fftreal(0) * fftreal(0)) + ...
                            (fftimag(0) * fftimag(0)))
                    print "DC Bias:" + str$(datavalue)
                else
                    if graphs(plotgraph).graphflags && UNBINNED_HISTOGRAM
                        y1 = graphs(plotgraph).zeroline
                        x1 = graphs(plotgraph).rect.left
                        offset = graphs(plotgraph).offset
                        print "Histogram: " + str$(offset)
                        for i = graphs(plotgraph).rect.left to graphs(plotgraph).rect.right
                            if offset >= graphs(plotgraph).datasize
                                exit
                            endif
                            y2 = y1 - (histogram(offset) * graphs(plotgraph).y_scale)
                            line x1, y1, x1, y2
                            inc x1, 1
                            inc offset, 1
                        next i
                        if offset >= graphs(plotgraph).datasize
                            offset = 0
                        endif
                    endif
                endif
            endif
        endif
        ink rgb(255, 0, 0), 0
        for i = graphs(plotgraph).rect.left to graphs(plotgraph).rect.right
            if i mod graphs(plotgraph).hMarks = 0
                line i, graphs(plotgraph).zeroline - 4, i, graphs(plotgraph).zeroline
            endif
        next i
    endif
endfunction offset
Hosted by www.Geocities.ws

1