[PATCH 3/4] msgsm32.acm: Add support for formats

Maarten Lankhorst (none) mlankhorst at patser.
Mon Aug 3 08:59:19 CDT 2009


---
 dlls/msgsm32.acm/msgsm32.c |  230 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 229 insertions(+), 1 deletions(-)

diff --git a/dlls/msgsm32.acm/msgsm32.c b/dlls/msgsm32.acm/msgsm32.c
index 7f8a1ec..098acd9 100644
--- a/dlls/msgsm32.acm/msgsm32.c
+++ b/dlls/msgsm32.acm/msgsm32.c
@@ -139,6 +139,229 @@ static	LRESULT GSM_DriverDetails(PACMDRIVERDETAILSW add)
     return MMSYSERR_NOERROR;
 }
 
+/* Validate a WAVEFORMATEX structure */
+static DWORD GSM_FormatValidate(const WAVEFORMATEX *wfx)
+{
+    if (wfx->nChannels != 1)
+        return 0;
+
+    switch (wfx->wFormatTag)
+    {
+    case WAVE_FORMAT_PCM:
+        if (wfx->wBitsPerSample != 16)
+        {
+            WARN("PCM wBitsPerSample %u\n", wfx->wBitsPerSample);
+            return 0;
+        }
+        if (wfx->nBlockAlign != 2)
+        {
+            WARN("PCM nBlockAlign %u\n", wfx->nBlockAlign);
+            return 0;
+        }
+        if (wfx->nAvgBytesPerSec != wfx->nBlockAlign * wfx->nSamplesPerSec)
+        {
+            WARN("PCM nAvgBytesPerSec %u/%u\n",
+                 wfx->nAvgBytesPerSec,
+                 wfx->nBlockAlign * wfx->nSamplesPerSec);
+            return 0;
+        }
+        return 1;
+    case WAVE_FORMAT_GSM610:
+        if (wfx->cbSize < sizeof(WORD))
+        {
+            WARN("GSM cbSize %u\n", wfx->cbSize);
+            return 0;
+        }
+        if (wfx->wBitsPerSample != 0)
+        {
+            WARN("GSM wBitsPerSample %u\n", wfx->wBitsPerSample);
+            return 0;
+        }
+        if (wfx->nBlockAlign != 65)
+        {
+            WARN("GSM nBlockAlign %u\n", wfx->nBlockAlign);
+            return 0;
+        }
+        if (((GSM610WAVEFORMAT*)wfx)->wSamplesPerBlock != 320)
+        {
+            WARN("GSM wSamplesPerBlock %u\n",
+                 ((GSM610WAVEFORMAT*)wfx)->wSamplesPerBlock);
+            return 0;
+        }
+        if (wfx->nAvgBytesPerSec != wfx->nSamplesPerSec * 65 / 320)
+        {
+            WARN("GSM nAvgBytesPerSec %d / %d\n",
+                 wfx->nAvgBytesPerSec, wfx->nSamplesPerSec * 65 / 320);
+            return 0;
+        }
+        return 1;
+    default:
+        return 0;
+    }
+    return 0;
+}
+
+static const DWORD gsm_rates[] = { 8000, 11025, 22050, 44100, 48000, 96000 };
+#define NUM_RATES (sizeof(gsm_rates)/sizeof(*gsm_rates))
+
+/***********************************************************************
+ *           GSM_FormatTagDetails
+ *
+ */
+static	LRESULT	GSM_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
+{
+    static const WCHAR szPcm[]={'P','C','M',0};
+    static const WCHAR szGsm[]={'G','S','M',' ','6','.','1','0',0};
+
+    switch (dwQuery)
+    {
+    case ACM_FORMATTAGDETAILSF_INDEX:
+	if (aftd->dwFormatTagIndex > 1) return ACMERR_NOTPOSSIBLE;
+	break;
+    case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
+	if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
+        {
+            aftd->dwFormatTagIndex = 1;
+	    break;
+	}
+	/* fall thru */
+    case ACM_FORMATTAGDETAILSF_FORMATTAG:
+	switch (aftd->dwFormatTag)
+        {
+	case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
+	case WAVE_FORMAT_GSM610: aftd->dwFormatTagIndex = 1; break;
+	default: return ACMERR_NOTPOSSIBLE;
+	}
+	break;
+    default:
+	WARN("Unsupported query %08x\n", dwQuery);
+	return MMSYSERR_NOTSUPPORTED;
+    }
+
+    aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+    switch (aftd->dwFormatTagIndex)
+    {
+    case 0:
+	aftd->dwFormatTag = WAVE_FORMAT_PCM;
+	aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
+	aftd->cStandardFormats = NUM_RATES;
+        lstrcpyW(aftd->szFormatTag, szPcm);
+        break;
+    case 1:
+	aftd->dwFormatTag = WAVE_FORMAT_GSM610;
+	aftd->cbFormatSize = sizeof(GSM610WAVEFORMAT);
+	aftd->cStandardFormats = NUM_RATES;
+        lstrcpyW(aftd->szFormatTag, szGsm);
+	break;
+    }
+    return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ *           GSM_FormatDetails
+ *
+ */
+static	LRESULT	GSM_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
+{
+    switch (dwQuery)
+    {
+    case ACM_FORMATDETAILSF_FORMAT:
+	if (!GSM_FormatValidate(afd->pwfx)) return ACMERR_NOTPOSSIBLE;
+	break;
+    case ACM_FORMATDETAILSF_INDEX:
+	afd->pwfx->wFormatTag = afd->dwFormatTag;
+	switch (afd->dwFormatTag)
+        {
+	case WAVE_FORMAT_PCM:
+	    if (afd->dwFormatIndex >= NUM_RATES) return ACMERR_NOTPOSSIBLE;
+	    afd->pwfx->nChannels = 1;
+	    afd->pwfx->nSamplesPerSec = gsm_rates[afd->dwFormatIndex];
+	    afd->pwfx->wBitsPerSample = 16;
+	    afd->pwfx->nBlockAlign = 2;
+	    afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
+	    break;
+	case WAVE_FORMAT_GSM610:
+            if (afd->dwFormatIndex >= NUM_RATES) return ACMERR_NOTPOSSIBLE;
+	    afd->pwfx->nChannels = 1;
+	    afd->pwfx->nSamplesPerSec = gsm_rates[afd->dwFormatIndex];
+	    afd->pwfx->wBitsPerSample = 0;
+	    afd->pwfx->nBlockAlign = 65;
+            afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * 65 / 320;
+            afd->pwfx->cbSize = sizeof(WORD);
+            ((GSM610WAVEFORMAT*)afd->pwfx)->wSamplesPerBlock = 320;
+	    break;
+	default:
+            WARN("Unsupported tag %08x\n", afd->dwFormatTag);
+	    return MMSYSERR_INVALPARAM;
+	}
+	break;
+    default:
+	WARN("Unsupported query %08x\n", dwQuery);
+	return MMSYSERR_NOTSUPPORTED;
+    }
+    afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
+    afd->szFormat[0] = 0; /* let MSACM format this for us... */
+
+    return MMSYSERR_NOERROR;
+}
+
+/***********************************************************************
+ *           GSM_FormatSuggest
+ *
+ */
+static	LRESULT	GSM_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
+{
+    /* some tests ... */
+    if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
+	adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
+	!GSM_FormatValidate(adfs->pwfxSrc)) return ACMERR_NOTPOSSIBLE;
+    /* FIXME: should do those tests against the real size (according to format tag */
+
+    /* If no suggestion for destination, then copy source value */
+    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
+	adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
+    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
+        adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
+
+    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
+    {
+	if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
+            adfs->pwfxDst->wBitsPerSample = 0;
+        else
+            adfs->pwfxDst->wBitsPerSample = 16;
+    }
+    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
+    {
+	switch (adfs->pwfxSrc->wFormatTag)
+        {
+        case WAVE_FORMAT_PCM: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_GSM610; break;
+        case WAVE_FORMAT_GSM610: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break;
+        }
+    }
+
+    /* recompute other values */
+    switch (adfs->pwfxDst->wFormatTag)
+    {
+    case WAVE_FORMAT_PCM:
+        adfs->pwfxDst->nBlockAlign = 2;
+        adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * 2;
+        break;
+    case WAVE_FORMAT_GSM610:
+        if (adfs->pwfxDst->cbSize < sizeof(WORD))
+            return ACMERR_NOTPOSSIBLE;
+        adfs->pwfxDst->nBlockAlign = 65;
+        adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * 65 / 320;
+        ((GSM610WAVEFORMAT*)adfs->pwfxDst)->wSamplesPerBlock = 320;
+        break;
+    default:
+        return ACMERR_NOTPOSSIBLE;
+    }
+
+    /* check if result is ok */
+    if (!GSM_FormatValidate(adfs->pwfxDst)) return ACMERR_NOTPOSSIBLE;
+    return MMSYSERR_NOERROR;
+}
+
 /**************************************************************************
  * 			GSM_DriverProc			[exported]
  */
@@ -168,10 +391,15 @@ LRESULT CALLBACK GSM_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
     case ACMDM_DRIVER_DETAILS:
 	return GSM_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
 
-    /* Not implemented yet */
     case ACMDM_FORMATTAG_DETAILS:
+	return GSM_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
+
     case ACMDM_FORMAT_DETAILS:
+	return GSM_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
+
     case ACMDM_FORMAT_SUGGEST:
+	return GSM_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
+
     case ACMDM_STREAM_OPEN:
     case ACMDM_STREAM_CLOSE:
     case ACMDM_STREAM_SIZE:
-- 
1.6.3.3


--------------050300090109010908080109--



More information about the wine-patches mailing list