converting c++ code to c#

oscilloscope using mic of sound card mixer control

Page 1 of 1

1 Replies - 7714 Views - Last Post: 20 June 2008 - 08:26 AM Rate Topic: -----

#1 samy19  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 20-June 08

converting c++ code to c#

Post icon  Posted 20 June 2008 - 07:24 AM

#include <stdio.h> 
#include <stdarg.h>
#include <windows.h>
#include <commctrl.h>
#include <mmsystem.h>

#include "resource.h"

#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")

// --- Global Variables ---
HINSTANCE   HInst = NULL;

void OutputDebugMsg (const char* pszFormat, ...)
{
	char buf[1024];
   	va_list arglist;
	
	va_start(arglist, pszFormat);
	vsprintf(buf, pszFormat, arglist);
	va_end(arglist);
	
	strcat(buf, "\n");
	OutputDebugString(buf);
}

void OutputMsgBox (const char* pszFormat, ...)
{
	char buf[1024];
	va_list arglist;
	
	va_start(arglist, pszFormat);
	vsprintf(buf, pszFormat, arglist);
	va_end(arglist);
	
	strcat(buf, "\n");
	MessageBox (NULL, buf, "", MB_IConstop);
}

/*********************** PrintWaveErrorMsg() **************************
 * Retrieves and displays an error message for the passed Wave In error
 * number. It does this using mciGetErrorString().
 *************************************************************************/

void PrintWaveErrorMsg(DWORD err, TCHAR * str)
{
	char	buffer[128];
	
	OutputMsgBox ("ERROR 0x%08X: %s\r\n", err, str);

	if (mciGetErrorString(err, &buffer[0], sizeof(buffer)))
	{
		OutputMsgBox ("%s\r\n", &buffer[0]);
	}
	else
	{
		OutputMsgBox ("0x%08X returned!\r\n", err);
	}
}


/*
What a long winded way to select recording input!

MIXERLINE_COMPONENTTYPE_SRC_ANALOG 
MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY 
MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC 
MIXERLINE_COMPONENTTYPE_SRC_DIGITAL 
MIXERLINE_COMPONENTTYPE_SRC_LINE 
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE 
MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER 
MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER 
MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE 
MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED 
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT 

*/
BOOL SetInputDevice (unsigned int inDev)
{
	HMIXER hMixer   = NULL;	   //declaring mixer
	int	inDevIdx = -1;

	//OPENS A SPECIFIC MIXER DEVICE AND ENSURES THAT THE DEVICE WILL NOT BE REMOVED UNTIL THE APP CLOSES
	if (mixerOpen(&hMixer, 0, 0, NULL, MIXER_OBJECTF_MIXER) != MMSYSERR_NOERROR)
	{
		return FALSE;
	}

	// get dwLineID
	MIXERLINE mxl;	//CREAT A MIXERLINE STRUCTURE CALLED mxl
	mxl.cbStruct		= sizeof(MIXERLINE);
	mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;//final recording source for the waveform-audio input(ADC)
	
	//RETRIVES INFO ABT A SPECIFIC LINE OF A MIXER DEVICE`		
	if (mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR)
	{
		mixerClose (hMixer);
		return FALSE;
	}

	// get dwControlID
	MIXERCONTROL	  mxc;	 //CREATS A MIXERCONTROL STRUCTURE CALLED mxc
	MIXERLINECONTROLS mxlc;		//CREATS A MIXERlineCONTROL STRUCTURE CALLED mxlc
	DWORD			 dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER;

	mxlc.cbStruct	  = sizeof(MIXERLINECONTROLS); 
	mxlc.dwLineID	  = mxl.dwLineID;  //mixer line control id= mixer line id
	mxlc.dwControlType = dwControlType;	//make control type mixer 
	mxlc.cControls	 = 0;				//number of mixercontrol element structure to retrive
	mxlc.cbmxctrl	  = sizeof(MIXERCONTROL);	//size in byte of a single mixerline control
	mxlc.pamxctrl	  = &mxc;			//pointer to one or more mixerctrl	

	if (mixerGetLineControls((HMIXEROBJ)hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR)
	{
		// no mixer, try MUX
		dwControlType	  = MIXERCONTROL_CONTROLTYPE_MUX; //
		mxlc.cbStruct	  = sizeof(MIXERLINECONTROLS);
		mxlc.dwLineID	  = mxl.dwLineID;
		mxlc.dwControlType = dwControlType;
		mxlc.cControls	 = 0;
		mxlc.cbmxctrl	  = sizeof(MIXERCONTROL);
		mxlc.pamxctrl	  = &mxc;
		if (mixerGetLineControls((HMIXEROBJ)hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR)
		{
			mixerClose (hMixer);
			return FALSE;
		}
	}

	if (mxc.cMultipleItems <= 0)
	{
		mixerClose (hMixer);
		return FALSE;
	}

	// get the index of the inDevice from available controls
	MIXERCONTROLDETAILS_LISTTEXT*  pmxcdSelectText = new MIXERCONTROLDETAILS_LISTTEXT[mxc.cMultipleItems];

	if (pmxcdSelectText != NULL)
	{
		MIXERCONTROLDETAILS mxcd;

		mxcd.cbStruct	   = sizeof(MIXERCONTROLDETAILS);
		mxcd.dwControlID	= mxc.dwControlID;
		mxcd.cChannels	  = 1;
		mxcd.cMultipleItems = mxc.cMultipleItems;
		mxcd.cbDetails	  = sizeof(MIXERCONTROLDETAILS_LISTTEXT);
		mxcd.paDetails	  = pmxcdSelectText;

		if (mixerGetControlDetails ((HMIXEROBJ)hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_LISTTEXT) == MMSYSERR_NOERROR)
		{
			// determine which controls the inputDevice source line
			DWORD dwi;
			for (dwi = 0; dwi < mxc.cMultipleItems; dwi++)
			{
				// get the line information
				MIXERLINE mxl;
				mxl.cbStruct = sizeof(MIXERLINE);
				mxl.dwLineID = pmxcdSelectText[dwi].dwParam1;
				if (mixerGetLineInfo ((HMIXEROBJ)hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID) == MMSYSERR_NOERROR && mxl.dwComponentType == inDev)
				{
					// found, dwi is the index.
					inDevIdx = dwi;
//					break;
				}
			}

		}

		delete []pmxcdSelectText;
	}

	if (inDevIdx < 0)
	{
		mixerClose (hMixer);
		return FALSE;
	}

	// get all the values first
	MIXERCONTROLDETAILS_BOOLEAN* pmxcdSelectValue = new MIXERCONTROLDETAILS_BOOLEAN[mxc.cMultipleItems];

	if (pmxcdSelectValue != NULL)
	{
		MIXERCONTROLDETAILS mxcd;
		mxcd.cbStruct	   = sizeof(MIXERCONTROLDETAILS);
		mxcd.dwControlID	= mxc.dwControlID;
		mxcd.cChannels	  = 1;
		mxcd.cMultipleItems = mxc.cMultipleItems;
		mxcd.cbDetails	  = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
		mxcd.paDetails	  = pmxcdSelectValue;
		if (mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR)
		{
			// ASSERT(m_dwControlType == MIXERCONTROL_CONTROLTYPE_MIXER || m_dwControlType == MIXERCONTROL_CONTROLTYPE_MUX);

			// MUX restricts the line selection to one source line at a time.
			if (dwControlType == MIXERCONTROL_CONTROLTYPE_MUX)
			{
				ZeroMemory(pmxcdSelectValue, mxc.cMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN));
			}

			// Turn on this input device
			pmxcdSelectValue[inDevIdx].fValue = 0x1;

			mxcd.cbStruct	   = sizeof(MIXERCONTROLDETAILS);
			mxcd.dwControlID	= mxc.dwControlID;
			mxcd.cChannels	  = 1;
			mxcd.cMultipleItems = mxc.cMultipleItems;
			mxcd.cbDetails	  = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
			mxcd.paDetails	  = pmxcdSelectValue;
			if (mixerSetControlDetails ((HMIXEROBJ)hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
			{
				delete []pmxcdSelectValue;
				mixerClose (hMixer);
				return FALSE;
			}
		}

		delete []pmxcdSelectValue;
	}

	mixerClose (hMixer);
	return TRUE;
}

// ***********************************************************************************

BOOL CALLBACK Scope (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{   
	static BOOL			 inRecord	 = FALSE;
	static HWAVEIN		 waveInHandle = NULL;
	static WAVEHDR		 waveHeader[2];	
	static WAVEFORMATEX	 waveFormat;
	static RECT			 drawArea;

	static HDC		   HdblDC		= NULL;
	static HBITMAP	   HdblOldBitmap = NULL;
	static int		   rps		   = 1;

	switch (message)
	{		
		case WM_INITDIALOG:
			{
				// Set the sound meter progress bars

				SendMessage (GetDlgItem (hwnd, IDC_REFESHSLIDER), TBM_SETRANGEMIN, FALSE, 1);
				SendMessage (GetDlgItem (hwnd, IDC_REFESHSLIDER), TBM_SETRANGEMAX, FALSE, 10);
				SendMessage (GetDlgItem (hwnd, IDC_REFESHSLIDER), TBM_SETPOS,	  FALSE, rps);				

				inRecord = FALSE;

				GetClientRect (hwnd, &drawArea);

				// create offscreen work area.
				HDC dc = GetDC (hwnd);
				HdblDC = CreateCompatibleDC (dc);
				HdblOldBitmap = CreateCompatibleBitmap (dc, drawArea.right, drawArea.bottom);
				HdblOldBitmap = (HBITMAP)SelectObject (HdblDC, HdblOldBitmap);
				ReleaseDC (hwnd, dc);
			}
			return TRUE;

		case WM_HSCROLL:
			switch (LOWORD (wParam))
			{
				case TB_THUMBTRACK:
				case TB_ENDTRACK:
					switch (GetDlgCtrlID((HWND)lParam))
					{
						case IDC_REFESHSLIDER:
							rps = SendMessage ((HWND)lParam, TBM_GETPOS, 0,0);
							break;
					}
					return TRUE;				
			}
			break;

		// Process user control message information.
		case WM_COMMAND:	
			switch (LOWORD (wParam))
			{
				case IDC_STOP:
					if (inRecord == FALSE)
						break;

					// Stop recording and tell the driver to unqueue/return all of our WAVEHDRs.
					// The driver will return any partially filled buffer that was currently
					// recording. Because we use waveInReset() instead of waveInStop(),
					// all of the other WAVEHDRs will also be returned via MM_WIM_DONE too
					waveInReset(waveInHandle);				 
					waveInUnprepareHeader (waveInHandle, &waveHeader[0], sizeof(WAVEHDR));
					waveInUnprepareHeader (waveInHandle, &waveHeader[1], sizeof(WAVEHDR));

					waveInClose(waveInHandle);
					VirtualFree(waveHeader[0].lpData, (waveHeader[0].dwBufferLength << 1), MEM_RELEASE); 
					inRecord = FALSE;

					SetInputDevice (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE);

					  break;

				case IDC_RECORD:
				{   
					if (inRecord != FALSE)
						break;

					// Set the recording input ... 
				   /* if (SetInputDevice (MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT) == FALSE)
					{
						if (SetInputDevice (MIXERLINE_COMPONENTTYPE_SRC_ANALOG) == FALSE)
						{
							if (SetInputDevice (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) == FALSE)
							{
								OutputMsgBox ("Error unable to set recording WAVEOUT device");
								break;
							}
						}
					}*/

					MMRESULT err;				   

					// Clear out both of our WAVEHDRs. At the very least, waveInPrepareHeader() expects the dwFlags field to be cleared
					ZeroMemory(&waveHeader[0], sizeof(WAVEHDR) * 2);

					// Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo. That's what I want to record 
					waveFormat.wFormatTag	  = WAVE_FORMAT_PCM;
					waveFormat.nChannels	   = 2;
					waveFormat.nSamplesPerSec  = 44100;
					waveFormat.wBitsPerSample  = 16;
					waveFormat.nBlockAlign	 = waveFormat.nChannels * (waveFormat.wBitsPerSample/8);
					waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
					waveFormat.cbSize		  = 0;

					// Open the default WAVE In Device, specifying my callback. Note that if this device doesn't
					// support 16-bit, 44KHz, stereo recording, then Windows will attempt to open another device
					// that does. So don't make any assumptions about the name of the device that opens. After
					// waveInOpen returns the handle, use waveInGetID to fetch its ID, and then waveInGetDevCaps
					// to retrieve the actual name							 
					if ((err = waveInOpen(&waveInHandle, WAVE_MAPPER, &waveFormat, (DWORD)hwnd, 0, CALLBACK_WINDOW)) != 0)
					{
						PrintWaveErrorMsg (err, "Can't open WAVE In Device!");
						break;
					}						

					// Allocate, prepare, and queue two buffers that the driver can use to record blocks of audio data.
					// (ie, We're using double-buffering. You can use more buffers if you'd like, and you should do that
					// if you suspect that you may lag the driver when you're writing a buffer to disk and are too slow
					// to requeue it with waveInAddBuffer. With more buffers, you can take your time requeueing
					// each).
					//
					// I'll allocate 2 buffers large enough to hold 2 seconds worth of waveform data at 44Khz. NOTE:
					// Just to make it easy, I'll use 1 call to VirtualAlloc to allocate both buffers, but you can
					// use 2 separate calls since the buffers do NOT need to be contiguous. You should do the latter if
					// using many, large buffers
					waveHeader[1].dwBufferLength = waveHeader[0].dwBufferLength = 512;
					if (!(waveHeader[0].lpData = (char*)VirtualAlloc(0, (waveHeader[0].dwBufferLength << 1), MEM_COMMIT, PAGE_READWRITE)))
					{
						OutputMsgBox ("ERROR: Can't allocate memory for WAVE buffer!\n");
						waveInClose(waveInHandle);
						break;
					}

					// Fill in WAVEHDR fields for buffer starting address. We've already filled in the size fields above */
					waveHeader[1].lpData = waveHeader[0].lpData + waveHeader[0].dwBufferLength;

					// Leave other WAVEHDR fields at 0 

					// Prepare the 2 WAVEHDR's 
					if ((err = waveInPrepareHeader(waveInHandle, &waveHeader[0], sizeof(WAVEHDR))))
					{
						waveInClose(waveInHandle);
						OutputMsgBox ("Error preparing WAVEHDR 1! -- %08X\n", err);
						VirtualFree (waveHeader[0].lpData, (waveHeader[0].dwBufferLength << 1), MEM_RELEASE); 
						break;
					}

					if ((err = waveInPrepareHeader(waveInHandle, &waveHeader[1], sizeof(WAVEHDR))))
					{
						waveInClose(waveInHandle);
						OutputMsgBox ("Error preparing WAVEHDR 2! -- %08X\n", err);
						VirtualFree (waveHeader[0].lpData, (waveHeader[0].dwBufferLength << 1), MEM_RELEASE); 
						break;
					}
					
					// Queue first WAVEHDR (recording hasn't started yet) 
					if ((err = waveInAddBuffer(waveInHandle, &waveHeader[0], sizeof(WAVEHDR))))
					{
						waveInClose(waveInHandle);
						OutputMsgBox ("Error queueing WAVEHDR 1! -- %08X\n", err);
						VirtualFree (waveHeader[0].lpData, (waveHeader[0].dwBufferLength << 1), MEM_RELEASE); 
						break;
					}

					// Queue second WAVEHDR 
					if ((err = waveInAddBuffer(waveInHandle, &waveHeader[1], sizeof(WAVEHDR))))
					{
						waveInClose(waveInHandle);
						OutputMsgBox ("Error queueing WAVEHDR 2! -- %08X\n", err);
						VirtualFree (waveHeader[0].lpData, (waveHeader[0].dwBufferLength << 1), MEM_RELEASE); 
						break;
					}

					// Start recording
					if ((err = waveInStart(waveInHandle)))
					{
						OutputMsgBox ("Error starting record! -- %08X\n", err);
						waveInClose(waveInHandle);							
						VirtualFree (waveHeader[0].lpData, (waveHeader[0].dwBufferLength << 1), MEM_RELEASE); 
						break;
					}
					inRecord = TRUE;
				}
			}
			break;
 
		case WM_CLOSE:
			SendMessage (hwnd, WM_COMMAND, MAKEWPARAM (IDC_STOP, 0), 0);			

			DeleteObject (SelectObject (HdblDC, HdblOldBitmap));
			DeleteDC (HdblDC);
			HdblDC		= NULL;
			HdblOldBitmap = NULL;

			EndDialog (hwnd, FALSE);
			return TRUE;

	
		// ---------- Process Audio Messages ---------
		case MM_WIM_DATA:
			{
				WAVEHDR* pHeader		= (WAVEHDR*) lParam;
			  static int refresh	  = 0;

			   refresh++;
				if (pHeader->dwBytesRecorded > 0)   //check if the buffer is not empty 
				{										
					
					// OutputDebugMsg ("Recorded %d bytes\n", pHeader->dwBytesRecorded);
					int		  idx	   = 0;
					short int*   pSamples  = (short int*)pHeader->lpData;  //pSamples points to the buffer
					int		  sampleCnt = pHeader->dwBytesRecorded/(sizeof(short int));  //512/2
					
					// ****** Draw an oscilloscope *******
					if ((refresh % rps) == 0) 
					{
						HDC hdc = GetDC (hwnd);

						SetViewportOrgEx (hdc, 0, 0, NULL);

//						HPEN hpen = CreatePen(PS_DOT,700,0x00000000);
//						POINT x1,x2; 
//						x1.x=50;
//						x1.y=150;
//						x2.x=800;
//						x2.y=150;
//						DrawLine(hpen,x1,x2);
//						CPen pen;
	
						HBRUSH hbr = CreateSolidBrush (0x0000bb88);  //make the brush color greenish
//					  HBRUSH hbr = CreateSolidBrush (GetSysColor (COLOR_BTNFACE));
						RECT	 r = drawArea;

						r.top = 25;
						r.right = 850;	//320
						r.left = 50;   //make the view center
						r.bottom = 650;	 //200		  
						
//						Graphics* g = button1->CreateGraphics();
//						Pen* myPen = new Pen(Color::Red);
//						myPen->SetWidth(5);
						
						FillRect (HdblDC,  &r, hbr);  //paint the oscilloscope with the brush
						DeleteObject (hbr);  // delet the brush					   
						
						float x=(float)0x7fff;
						float sampReduce = (float)(r.bottom / 4) / (float)x;
						float xStep	  = (float)r.right / (float)(sampleCnt/2);
						int   yPos	   = -1;
						float xPos	   = xStep;						

						int yPosLeft   = (int)yPos;
						int yPosRight  = r.bottom  - (r.bottom / 4);						

						 MoveToEx (HdblDC, (int)((float)xPos-xStep), yPos, NULL);

						for (int idx = 0; idx < sampleCnt; idx += 2)
						{
							int y=(int)((float)xPos-xStep);
							MoveToEx (HdblDC, (int)y, yPosLeft, NULL);
							yPos = (r.bottom / 4);
							
							float zzz=pSamples[idx];
							int z=(int)(zzz * sampReduce);
							yPosLeft = yPos + z;
							if (idx > 0)
								LineTo (HdblDC, (int)xPos, yPosLeft);

							yPos = (r.bottom  - (r.bottom / 4));

							int yy=(int)((float)xPos-xStep);
							MoveToEx (HdblDC, (int)yy, yPosRight, NULL);
							yPosRight = yPos + (int)((float)pSamples[idx+1] * sampReduce);

							if (idx > 0)
								LineTo   (HdblDC, (int)xPos, yPosRight);

							xPos += xStep;
						}

						BitBlt (hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, HdblDC, r.left, r.top, SRCCOPY);

						ReleaseDC (hwnd, hdc);
					}

				}
				
				if (inRecord) // Are we still recording? 
				{
					// Yes. Now we need to requeue this buffer so the driver can use it for another block of audio
					// data. NOTE: We shouldn't need to waveInPrepareHeader() a WAVEHDR that has already been prepared once					
					waveInAddBuffer(waveInHandle, pHeader, sizeof(WAVEHDR));
				}
			}
			break;
						
		case MM_WIM_OPEN:   // Our main thread is opening the WAVE device 
			OutputDebugMsg ("Open \n");
			break;
		
		case MM_WIM_CLOSE:  // waveInClose() responce
			OutputDebugMsg ("Close \n");
			return 0;							
	}
			  
	return FALSE;
}


// ***********************************************************************************

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
	HInst = hInstance;

	InitCommonControls ();

	DialogBox (HInst, MAKEINTRESOURCE (IDD_SCOPE), NULL, (DLGPROC) Scope);					   

	return 0;
}


Is This A Good Question/Topic? 0
  • +

Replies To: converting c++ code to c#

#2 zakary  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 27
  • View blog
  • Posts: 427
  • Joined: 15-February 05

Re: converting c++ code to c#

Posted 20 June 2008 - 08:26 AM

yeah you can convert it but you need to try it first and when and if it does not work then post your C# code and we will help you
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1