Signalogic Logo.

DSP Hardware, DSP Software

C54xx C67xx DSP

MATLAB DSP, media gateway DSP, wireless DSP, PC/104 DSP

Digital Tape Recorder C/C++ Source Code Example

Digital Tape Recorder C/C++ Source Code Example of Using DirectDSP® software

Below is a C/C++ source code example of using off-the-shelf DSP/analog hardware to perform a basic digital tape recorder function. Note the use of the DSShowHardwareSelector call to bring up a list of supported hardware. Note also the DSAcquireWvfrmFile and DSGenerateWvfrmFile calls used in asynchronous mode, which allows waveform files to be processed in the background.

#include <windows.h>
#include <stdlib.h>

// DirectDSP® software package include files

#include "enmgr.h"   // Engine Manager
#include "hwmgr.h"   // Hardware Manager
#include "hwlib.h"   // Hardware Library


// some global variables

  ...note:  many variable and type declarations omitted for brevity...

HANDLE FAR  hEngine = NULL;  // declare at least one variable FAR to limit this 
to a single-instance program
HANDLE      hBoard = NULL;
BOOL        fBoardInitialized = FALSE;
char        szBoard[30];
HWND        hdlgDtape = NULL;

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInst, LPSTR lpszCmdParam, int nCmdShow) {

 // comment this call if status messages from HwLib should not be visible

    DSShowEngMgrStatusWindow();  // turn on debug status window in Engine Manager


 // show hardware selector dialog (Hardware Manager); returns board designator string
 // note:  if hardware choice is fixed, then skip this call and use correct board designator
 // string in DSAssignBoard call below

    if (DSShowHardwareSelectorDlg(NULL, szBoard) == IDCANCEL) goto Cleanup;


 // create tape recorder display panel as modeless dialog (see WM_INITDIALOG below)

    hdlgDtape = CreateDialog(hInstance, "Dtape", NULL, (DLGPROC)DlgProc);  // dialog box 
in dtape.rc needs some bwcc controls

    if (hdlgDtape == NULL) {

        MessageBox(GetActiveWindow(), "could not create tape recorder dialog box", 
szApp, MB_OK);
        goto Cleanup;
    }

    ShowWindow(hdlgDtape, SW_SHOW);
    UpdateWindow(hdlgDtape);


 // open engine

    hEngine = DSEngineOpen(DS_EO_HSM, NULL);  // first try to open Hypersignal-Macro or
                                              // Hypersignal-Macro EX as engine

    if (IsWindowVisible(hdlgDtape)) SetActiveWindow(hdlgDtape);

    if (!hEngine) {

        hEngine = DSEngineOpen(DS_EO_HSA, NULL);  // if that doesn't work, try
                                                  // Hypersignal-Acoustic
        if (!hEngine) {

            itoa(DSGetHWLibErrorStatus(), tmpstr, 10);
            lstrcat(tmpstr, " is error code; DSEngineOpen failed");
            MessageBox(GetActiveWindow(), tmpstr, szApp, MB_OK);
            goto Cleanup;
        }
    }


 // assign a board handle:  engine handle, board designator string, instruction set, 
IO base addr, Mem base addr

    hBoard = DSAssignBoard(hEngine, szBoard, NULL, NULL, NULL);  // use defaults where 
possible

 // initialize the board; make sure it's installed and responded

    fBoardInitialized = DSInitBoard(hBoard);

    if (!fBoardInitialized) {

        itoa(DSGetEngineErrorStatus(hEngine), tmpstr, 10);
        lstrcat(tmpstr, " is error code; DSInitBoard failed");
        MessageBox(GetActiveWindow(), tmpstr, szApp, MB_OK);
        goto Cleanup;
    }


 // register dialog box window to receive various messages from engine

    DSRegisterEngineMsgWnd(hEngine, DS_REMW_SETPROGSTATUSMSG | DS_REMW_SETSTATISTICSMSG 
| DS_REMW_SETBUFNUMMSG | DS_REMW_SETLEVELMSG, hdlgDtape);


 // start processing dialog window messages

    while (GetMessage(&msg, NULL, 0, 0)) {

        if (IsDialogMessage(hdlgDtape, &msg)) continue;

        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }


Cleanup:

    if (hdlgDtape != NULL) SendMessage(hdlgDtape, WM_CLOSE, 0, 0L);

    if (fBoardInitialized) DSDisableBoard(hBoard);

    if (hBoard != NULL) DSFreeBoard(hBoard);

    if (hEngine != NULL) DSEngineClose(hEngine);

    return (int)hdlgDtape;
}

BOOL FAR PASCAL _export DlgProc(HWND hdlg, WORD wMsg, WORD wParam, LONG lParam) {

    ...note:  most variable declarations omitted for brevity...

HCTRLITEMS       hCtrlItems;
PCTRLITEMS       pCtrlItems;
HGLOBAL          hConvInfo;
PCONVERSIONINFO  pConvInfo;


    switch (wMsg) {

    ...note:  other message-processing code omitted for brevity...

        case WM_COMMAND:

            switch (wParam) {

                case DS_ATC_TAPEPAUSE:

                    if (State == PAUSE) {

                        DSSendEngineCommand(hEngine, DS_SEC_RESUME, DS_EEF_ASYNC);

                        State = BeforePauseState;
                    }
                    else {

                        if (State != IDLE) DSSendEngineCommand(hEngine, DS_SEC_PAUSE, 
			DS_EEF_ASYNC);

                        BeforePauseState = State;
                        State = PAUSE;
                    }

                    break;


                case DS_ATC_TAPESTOP:

                 // if needed, "unclick" the PAUSE button (on separate toolbar), 
		cause return to pre-Pause state

                    if (State == PAUSE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPEPAUSE, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar, DS_ATC_TAPEPAUSE), BN_CLICKED));

                    if (State != IDLE) {

                     // clear menu checks, in case

                        if (State == PLAYING) DSSendMessageToolboxControl(hToolbar2, 
		DS_ATC_TAPEPLAY, WM_SETBUTTONSTATE, 0, 0L);
                        else if (State == RECORDING) DSSendMessageToolboxControl
		(hToolbar2, DS_ATC_TAPERECORD, WM_SETBUTTONSTATE, 0, 0L);

                        State = IDLE;  // change state

                        if (lParam != CMDNOTIFY) {

                            DSSendEngineCommand(hEngine, DS_SEC_IDLE, DS_EEF_SYNC);  
		// if message didn't come from WM_DSPENGINE_PROGSTATUS, tell engine to idle 
		(wait for confirmation)
                        }
                    }

                    break;


                case DS_ATC_TAPEPLAY:

                 // if needed, "unclick" the PAUSE button (on separate toolbar), cause 
		return to pre-Pause state

                    if (State == PAUSE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPEPAUSE, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar, DS_ATC_TAPEPAUSE), BN_CLICKED));

                 // process Stop button if already running

                    PrevState = State;  // save, because Stop button will set back to IDLE

                    if (State != IDLE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPESTOP, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar2, DS_ATC_TAPESTOP), BN_CLICKED));

                    if (PrevState == PLAYING) State = IDLE;
                    else State = PLAYING;


                    if (State == IDLE) break;


                 // get output filename

                    DSSendMessageToolboxControl(hToolbar3, OUTWAVFILENAME, WM_GETTEXT, 
		sizeof(szFilename), (LPARAM)(LPSTR)szFilename);


                 // create CONVERSIONINFO object memory

                 // NOTES:

                 // 1) zero-init of allocated memory sets most parameters to default 
			values

                 // 2) FOR D/A OUTPUT ONLY, a 0 value for number of channels, sampling 
			frequency,
                 //    and number of samples causes engine to "auto configure", 
		initializing these
                 //    values from waveform file header

                    hConvInfo = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | 
		GMEM_DISCARDABLE, sizeof(CONVERSIONINFO));
                    pConvInfo = (PCONVERSIONINFO)GlobalLock(hConvInfo);

                    lstrcpy(pConvInfo->szFilename, szFilename);
                    pConvInfo->NumChan = 0;      // auto-configure (see note above)
                    pConvInfo->Fs = 0;           //       "
                    pConvInfo->NumSamples = 0;   //       "
                    lstrcpy(pConvInfo->szGainList, "1");  // output gain/attenuation 
			(enterable in Volts, dB, channel-specific, or channel-range)
                    pConvInfo->DALooping = TRUE;  // cause output to repeat

                    if (!DSGenerateWvfrmFile(hBoard, pConvInfo, DS_AWF_ASYNC)) 
		{  // start playback (asynchronous operation--don't wait for file to complete)

                        if (State == PLAYING) SendMessage(hdlg, WM_COMMAND, 
		DS_ATC_TAPESTOP, CMDNOTIFY);  // error: unstick button, etc. (use impossible value:  
		window handle == NULL, 2 is not menu or accelerator)
                    }
                    else {

                     // update play filename box with file being recorded

                        DSInsertControlItem(hOutputFileEntry, szFilename, 0);  // 
			add to listbox

                        DSSetControlText(hOutputFileEntry, szFilename);  // set edit text
                    }

                    GlobalUnlock(hConvInfo);
                    GlobalFree(hConvInfo);

                    break;


                case DS_ATC_TAPEFASTFORWARD:

                 // if needed, "unclick" the PAUSE button (on separate toolbar), 
		cause return to pre-Pause state

                    if (State == PAUSE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPEPAUSE, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar, DS_ATC_TAPEPAUSE), BN_CLICKED));

                 // process Stop button if already running

                    if (State != IDLE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPESTOP, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar2, DS_ATC_TAPESTOP), BN_CLICKED));

                    State = IDLE;

                    break;


                case DS_ATC_TAPEREWIND:

                 // if needed, "unclick" the PAUSE button (on separate toolbar), cause 
		return to pre-Pause state

                    if (State == PAUSE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPEPAUSE, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar, DS_ATC_TAPEPAUSE), BN_CLICKED));

                 // process Stop button if already running

                    if (State != IDLE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPESTOP, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar2, DS_ATC_TAPESTOP), BN_CLICKED));

                    State = IDLE;

                    break;


                case DS_ATC_TAPERECORD:

                 // if needed, "unclick" the PAUSE button (on separate toolbar), cause 
			return to pre-Pause state

                    if (State == PAUSE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPEPAUSE, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar, DS_ATC_TAPEPAUSE), BN_CLICKED));

                 // process Stop button if already running

                    PrevState = State;  // save, because Stop button will set back to IDLE

                    if (State != IDLE) SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPESTOP, 
		MAKELPARAM(DSGetToolboxControlWindow(hToolbar2, DS_ATC_TAPESTOP), BN_CLICKED));

                    if (PrevState == RECORDING) State = IDLE;
                    else State = RECORDING;


                    if (State == IDLE) break;


                 // get current record filename

                    DSSendMessageToolboxControl(hToolbar3, INWAVFILENAME, WM_GETTEXT, 
			sizeof(szFilename), (LPARAM)(LPSTR)szFilename);


                 // create CONVERSIONINFO object memory

                 // NOTES:

                 // 1) zero-init of allocated memory sets most parameters to default values

                    hConvInfo = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DISCARDABLE, 
			sizeof(CONVERSIONINFO));
                    pConvInfo = (PCONVERSIONINFO)GlobalLock(hConvInfo);

                    lstrcpy(pConvInfo->szFilename, szFilename);
                    pConvInfo->NumChan = 1;          // one channel

                    for (j=0; jNumChan; j++) pConvInfo->ChanList[j] = j;  // 
		example of initializing channel list

                    pConvInfo->Fs = 22050;            // 22.05 kHz sampling rate
                    pConvInfo->NumSamples = 100000L;  // 100,000 samples
                    lstrcpy(pConvInfo->szGainList, "1");  // input gain/attenuation 
			(enterable in Volts, dB, channel-specific, or channel-range)

                    pConvInfo->NumTrigChan = 1;
                    pConvInfo->TrigChanList[0] = 0;

                    pConvInfo->StoreOnAbort = TRUE;  // store data if operation is aborted

                    pConvInfo->Monitor = fMonitorMode;

                    if (!DSAcquireWvfrmFile(hBoard, pConvInfo, DS_AWF_ASYNC)) {  // start 
			record (asynchronous operation--don't wait for file to complete)

                        if (State == RECORDING) SendMessage(hdlg, WM_COMMAND, 
			DS_ATC_TAPESTOP, CMDNOTIFY);  // error: unstick button, etc.
                    }
                    else {

                     // update both record and play filename boxes with file being recorded

                        DSInsertControlItem(hInputFileEntry, szFilename, 0);  // add to listbox
                        DSSetControlText(hInputFileEntry, szFilename);  // set edit text

                        DSInsertControlItem(hOutputFileEntry, szFilename, 0);
                        DSSetControlText(hOutputFileEntry, szFilename);
                    }

                    GlobalUnlock(hConvInfo);
                    GlobalFree(hConvInfo);

                    break;


                case DS_ATC_MONITORMODE:

                    fMonitorMode ^= 1;

                    break;
            }

            break;


        case WM_DSPENGINE_PROGSTATUS:
          
         // if engine has returned to idle state because the current program is finished, ran
         // into an error, etc. process STOP button to reflect the current status

            if (State != IDLE && LOWORD(lParam) == DS_PS_PROGDONE) {

                SendMessage(hdlg, WM_COMMAND, DS_ATC_TAPESTOP, CMDNOTIFY);
            }

            break;

        default:

            return FALSE;
    }

    return TRUE;
}


Hypersignal is a registered trademark of Hyperception. Signalogic, DirectDSP, and DSPower are registered trademarks, and VDS, DirectRT, SigBook, Visual Bench, and Real-Time Convolver are trademarks of Signalogic. MATLAB is a registered trademark of The MathWorks. Telogy Networks is a registered trademark of Texas Instruments-Telogy. LabVIEW is a registered trademark of National Instruments. Windows and Visual Studio are trademarks of Microsoft.

Some of the pictures used on this website Copyright © 2002 by Daniel Speck at FreeStockPhotos.com