6
votes

Jouer un son arbitraire sur Windows?

Comment puis-je, disons, jouez un son avec une amplitude donnée et un maquillage de fréquence donné (disons, composé de fréquences 2 kHz et 3 kHz) de manière natale sous Windows (32 bits et 64 bits, jusqu'à Windows 7) ?

(par natif, je veux dire sans utiliser de bibliothèque externe.)

Je crois que cela a besoin de méthode WaveOutwrite mais je n'ai aucune idée Comment ça marche.


0 commentaires

4 Réponses :


2
votes

bip Xxx


0 commentaires

0
votes

bip via le haut-parleur PC ou en utilisant DirectX Sound. Je peux offrir des extraits si vous avez besoin.


3 commentaires

Eh bien, la fonction Beep ne fonctionne pas car elle ne peut pas générer une combinaison de fréquences. DirectX Sound semble être surkill, car je veux juste générer une tonalité simple ... y a-t-il un moyen de le faire avec quelque chose comme WaveOutwrite ? Je pense que c'est la bonne façon, mais je n'ai aucune idée de quelles données pour le donner.


@Mehrdad: WavOutwrite s'attend à ce que le format WAV au format WAV, IIRC.


@Adam: ah maintenant que est une bonne réponse. =) N'hésitez pas à poster cela pour que je puisse l'accepter! (BTW, est-ce que c'est la complète des données vagues ou une seule partie de celui-ci? Dois-je aussi envoyer tous les en-têtes de riff?)



1
votes

the Waveout Fonctions traite des données de forme d'onde SON (au format WAV, si je vous rappelle correctement).

Bien que cela soit ciblé sur les applications WPF, le lien suivant devrait s'avérer utile pour toute application de bureau:

génération de son dans les applications WPF


0 commentaires

4
votes

J'ai quelque chose de travail ...

#define _USE_MATH_DEFINES 1
#include <math.h>
#include <stdio.h>
#include <tchar.h>

#include <windows.h>
#include <mmreg.h>
#include <complex>

#pragma comment(lib, "Winmm.lib")

MMRESULT play(float nSeconds,
    float signal(float timeInSeconds, unsigned short channel, void *context),
    void *context = NULL, unsigned long samplesPerSecond = 48000)
{
    UINT timePeriod = 1;

    MMRESULT mmresult = MMSYSERR_NOERROR;
    WAVEFORMATEX waveFormat = {0};
    waveFormat.cbSize = 0;
    waveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
    waveFormat.nChannels = 2;
    waveFormat.nSamplesPerSec = samplesPerSecond;
    const size_t nBuffer =
        (size_t)(nSeconds * waveFormat.nChannels * waveFormat.nSamplesPerSec);
    float *buffer;
    waveFormat.wBitsPerSample = CHAR_BIT * sizeof(buffer[0]);
    waveFormat.nBlockAlign =
        waveFormat.nChannels * waveFormat.wBitsPerSample / CHAR_BIT;
    waveFormat.nAvgBytesPerSec =
        waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;

    buffer = (float *)calloc(nBuffer, sizeof(*buffer));
    __try
    {
        for (size_t i = 0; i < nBuffer; i += waveFormat.nChannels)
            for (unsigned short j = 0; j < waveFormat.nChannels; j++)
                buffer[i+j] = signal((i+j) * nSeconds / nBuffer, j, context);
        HWAVEOUT hWavOut = NULL;
        mmresult = waveOutOpen(&hWavOut, WAVE_MAPPER,
            &waveFormat, NULL, NULL, CALLBACK_NULL);
        if (mmresult == MMSYSERR_NOERROR)
        {
            __try
            {
                timeBeginPeriod(timePeriod);
                __try
                {
                    WAVEHDR hdr = {0};
                    hdr.dwBufferLength =
                        (ULONG)(nBuffer * sizeof(buffer[0]));
                    hdr.lpData = (LPSTR)&buffer[0];
                    mmresult = waveOutPrepareHeader(hWavOut,
                        &hdr, sizeof(hdr));
                    if (mmresult == MMSYSERR_NOERROR)
                    {
                        __try
                        {
                            ULONG start = GetTickCount();
                            mmresult =
                                waveOutWrite(hWavOut, &hdr, sizeof(hdr));
                            Sleep((ULONG)(1000 * nSeconds
                                - (GetTickCount() - start)));
                        }
                        __finally
                        { waveOutUnprepareHeader(hWavOut, &hdr, sizeof(hdr)); }
                    }
                }
                __finally { timeEndPeriod(timePeriod); }
            }
            __finally { waveOutClose(hWavOut); }
        }
    }
    __finally { free(buffer); }
    return mmresult;
}

// Triangle wave generator
float triangle(float timeInSeconds, unsigned short channel, void *context)
{
    const float frequency = *(const float *)context;
    const float angle = (float)(frequency * 2 * M_PI * timeInSeconds);
    switch (channel)
    {
        case  0: return (float)asin(sin(angle + 0 * M_PI / 2));
        default: return (float)asin(sin(angle + 1 * M_PI / 2));
    }
}

// Pure tone generator
float pure(float timeInSeconds, unsigned short channel, void *context)
{
    const float frequency = *(const float *)context;
    const float angle = (float)(frequency * 2 * M_PI * timeInSeconds);
    switch (channel)
    {
        case  0: return (float)sin(angle + 0 * M_PI / 2);
        default: return (float)sin(angle + 1 * M_PI / 2);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    float frequency = 2 * 261.626F;
    play(1, pure, &frequency);
    return 0;
}


1 commentaires

+1. Mais je pense que le générateur de vagues triangle est faux. Selon Wikipedia : retour (flotteur) Asin (NAS (angle + 0 * M_PI / 2)) * 2 / M_PI; .