#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;
}
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
#1
converting c++ code to c#
Posted 20 June 2008 - 07:24 AM
Replies To: converting c++ code to c#
#2
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
Page 1 of 1
|
|

New Topic/Question
Reply




MultiQuote




|