2013-11-10 7 views
2

Использование C++ 11 в Visual Studio 2012, я пытаюсь звучать, что я наблюдал в Паскале. В Паскале кажется, что вы можете отправить частоту внутреннему громкоговорителю, который воспроизводит эту частоту, пока вы не скажете ей остановиться (или пока вы не скажете, чтобы она воспроизводила другую частоту). Так вот, что мне нужно:Простые звуки в C++

  • я должен быть в состоянии определить частоту звука
  • Звук должен иметь мало или нет разрыва (до, возможно, 5мс было бы приемлем)
  • Я не хочу для использования внешних звуковых библиотек (пожалуйста, не тратьте свое время, предлагая их, если они не являются невероятно легкими и обеспечивают исключительно широкий диапазон использования)
  • Предпочтительно, звук воспроизводится на внутреннем динамике, а не через компьютерные штатные динамики

Я не могу найти какие-либо совместимые с возможностями библиотеки/заголовки в визуальной студии, которые предоставляют возможность посылать сигнал на внутренний динамик. Я готов попытаться работать напрямую с внутренним докладчиком (я знаю, что это будет сложно, но я не идиот), я думаю, что смогу понять это с некоторыми рекомендациями), но я не могу найти никакой документации при доступе к внутреннему динамику в Windows.

EDIT: От this post я смог собрать, что большинство компьютеров в настоящее время на самом деле не имеют внутреннего динамика. Облом. Это нормально, хотя - я могу использовать подключенные акустические системы, но я до сих пор имею следующие требования:

  • Мне нужно, чтобы иметь возможность определить частоту и имеет колонки играть в эту частоту, пока я не скажу им, чтобы остановить
  • Я предпочел бы не использовать внешние библиотеки

EDIT 2: Вот класс, я работаю над:

#define HALF_NOTE 1.059463094359 // HALF_NOTE^12 = 2 

#include <Windows.h> 
#include <math.h> 

class SoundEffect 
{ 
public: 
    SoundEffect(){} 

    void Play() 
    { 
     for (int i = 0; data[i + 1] > 0; i++) 
     { 
      Beep(16 * pow(HALF_NOTE, data[i++] - 1), data[i] * 10); // (frequency of c0) * (twelfth root of 2)^(number of half steps above c0) 

      // Ideally, the code would look more like this (pseudocode): 
      // sound(16 * pow(HALF_NOTE, data[i++] - 1)); // Start playing the specified frequency 
      // delay(data[i] * 10); 
     } 
     // nosound(); 
    } 

    int& operator[] (int location) { return data[location]; } 

private: 
    int data[256]; 
}; 
+0

Что-то вроде [Beep] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms679277 (v = vs.85) .aspx)? –

+1

В тот день эти звуки не воспроизводились «прямо на звуковой карте», а из внутреннего динамика. На ПК практически не было звуковых карт, пока Паскаль больше не использовался. – Timbo

+0

Машины больше не имеют громкоговорителей. Угадайте, почему Beep() все еще работает :) –

ответ

1

В результате я использовал API мультимедиа Windows для создания осциллограмм и отправки их на звуковое устройство. Я основывал свое решение на уроке here. Вот что я закончил с:

#define HALF_NOTE 1.059463094359 // HALF_NOTE^12 = 2 
#define PI 3.14159265358979 

#include <Windows.h> 
#include <math.h> 
using namespace std; 

class SoundEffect 
{ 
public: 
    SoundEffect() 
    { 
     m_data = NULL; 
    } 
    SoundEffect(const int noteInfo[], const int arraySize) 
    { 
     // Initialize the sound format we will request from sound card 
     m_waveFormat.wFormatTag = WAVE_FORMAT_PCM;  // Uncompressed sound format 
     m_waveFormat.nChannels = 1;     // 1 = Mono, 2 = Stereo 
     m_waveFormat.wBitsPerSample = 8;    // Bits per sample per channel 
     m_waveFormat.nSamplesPerSec = 11025;   // Sample Per Second 
     m_waveFormat.nBlockAlign = m_waveFormat.nChannels * m_waveFormat.wBitsPerSample/8; 
     m_waveFormat.nAvgBytesPerSec = m_waveFormat.nSamplesPerSec * m_waveFormat.nBlockAlign; 
     m_waveFormat.cbSize = 0; 

     int dataLength = 0, moment = (m_waveFormat.nSamplesPerSec/75); 
     double period = 2.0 * PI/(double) m_waveFormat.nSamplesPerSec; 

     // Calculate how long we need the sound buffer to be 
     for (int i = 1; i < arraySize; i += 2) 
      dataLength += (noteInfo[i] != 0) ? noteInfo[i] * moment : moment; 

     // Allocate the array 
     m_data = new char[m_bufferSize = dataLength]; 

     int placeInData = 0; 

     // Make the sound buffer 
     for (int i = 0; i < arraySize; i += 2) 
     { 
      int relativePlaceInData = placeInData; 

      while ((relativePlaceInData - placeInData) < ((noteInfo[i + 1] != 0) ? noteInfo[i + 1] * moment : moment)) 
      { 
       // Generate the sound wave (as a sinusoid) 
       // - x will have a range of -1 to +1 
       double x = sin((relativePlaceInData - placeInData) * 55 * pow(HALF_NOTE, noteInfo[i]) * period); 

       // Scale x to a range of 0-255 (signed char) for 8 bit sound reproduction 
       m_data[relativePlaceInData] = (char) (127 * x + 128); 

       relativePlaceInData++; 
      } 

      placeInData = relativePlaceInData; 
     } 
    } 
    SoundEffect(SoundEffect& otherInstance) 
    { 
     m_bufferSize = otherInstance.m_bufferSize; 
     m_waveFormat = otherInstance.m_waveFormat; 

     if (m_bufferSize > 0) 
     { 
      m_data = new char[m_bufferSize]; 

      for (int i = 0; i < otherInstance.m_bufferSize; i++) 
       m_data[i] = otherInstance.m_data[i]; 
     } 
    } 
    ~SoundEffect() 
    { 
     if (m_bufferSize > 0) 
      delete [] m_data; 
    } 

    SoundEffect& operator=(SoundEffect& otherInstance) 
    { 
     if (m_bufferSize > 0) 
      delete [] m_data; 

     m_bufferSize = otherInstance.m_bufferSize; 
     m_waveFormat = otherInstance.m_waveFormat; 

     if (m_bufferSize > 0) 
     { 
      m_data = new char[m_bufferSize]; 

      for (int i = 0; i < otherInstance.m_bufferSize; i++) 
       m_data[i] = otherInstance.m_data[i]; 
     } 

     return *this; 
    } 

    void Play() 
    { 
     // Create our "Sound is Done" event 
     m_done = CreateEvent (0, FALSE, FALSE, 0); 

     // Open the audio device 
     if (waveOutOpen(&m_waveOut, 0, &m_waveFormat, (DWORD) m_done, 0, CALLBACK_EVENT) != MMSYSERR_NOERROR) 
     { 
      cout << "Sound card cannot be opened." << endl; 
      return; 
     } 

     // Create the wave header for our sound buffer 
     m_waveHeader.lpData = m_data; 
     m_waveHeader.dwBufferLength = m_bufferSize; 
     m_waveHeader.dwFlags = 0; 
     m_waveHeader.dwLoops = 0; 

     // Prepare the header for playback on sound card 
     if (waveOutPrepareHeader(m_waveOut, &m_waveHeader, sizeof(m_waveHeader)) != MMSYSERR_NOERROR) 
     { 
      cout << "Error preparing Header!" << endl; 
      return; 
     } 

     // Play the sound! 
     ResetEvent(m_done); // Reset our Event so it is non-signaled, it will be signaled again with buffer finished 

     if (waveOutWrite(m_waveOut, &m_waveHeader, sizeof(m_waveHeader)) != MMSYSERR_NOERROR) 
     { 
      cout << "Error writing to sound card!" << endl; 
      return; 
     } 

     // Wait until sound finishes playing 
     if (WaitForSingleObject(m_done, INFINITE) != WAIT_OBJECT_0) 
     { 
      cout << "Error waiting for sound to finish" << endl; 
      return; 
     } 

     // Unprepare our wav header 
     if (waveOutUnprepareHeader(m_waveOut, &m_waveHeader,sizeof(m_waveHeader)) != MMSYSERR_NOERROR) 
     { 
      cout << "Error unpreparing header!" << endl; 
      return; 
     } 

     // Close the wav device 
     if (waveOutClose(m_waveOut) != MMSYSERR_NOERROR) 
     { 
      cout << "Sound card cannot be closed!" << endl; 
      return; 
     } 

     // Release our event handle 
     CloseHandle(m_done); 
    } 

private: 
    HWAVEOUT m_waveOut; // Handle to sound card output 
    WAVEFORMATEX m_waveFormat; // The sound format 
    WAVEHDR m_waveHeader; // WAVE header for our sound data 
    HANDLE m_done; // Event Handle that tells us the sound has finished being played. 
        // This is a very efficient way to put the program to sleep 
        // while the sound card is processing the sound buffer 

    char* m_data; // Sound data buffer 
    int m_bufferSize; // Size of sound data buffer 
}; 

Довольно сложный, но он работает.Я использую его с текстовыми файлами, как это (звуковые эффекты для DOS Марио & Luigi):

LifeMusic 56 8 61 8 65 8 61 8 63 8 68 8 
GrowMusic 37 4 44 4 49 4 38 4 45 4 50 4 39 4 46 4 51 4 
CoinMusic 66 1 
PipeMusic 13 0 13 8 1 0 1 16 13 0 13 8 1 0 1 16 13 0 13 8 1 0 1 16 
FireMusic 41 1 46 1 
HitMusic 25 2 13 3 1 4 25 1 13 2 1 3 
DeadMusic 25 3 13 4 1 6 
NoteMusic 1 3 13 4 1 6 
StarMusic 37 4 41 4 44 4 49 4 53 4 56 4 61 4 65 4 68 4 73 4 

Чтобы дать краткий обзор, мой основной файл читает эти строки. Для каждой строки он создает звуковой эффект из массива целых чисел и создает карту, где ключи являются именами звуковых эффектов, а значениями являются созданные экземпляры SoundEffect.

В текстовом файле каждая строка должна иметь четное число целых чисел. Если вы разбиваете одну строку целых чисел на пары, первое число будет числом половин шагов выше А1 (чтобы определить частоту), а второе число будет длительностью в 75-е секунды (произвольное, I знаю).

1

Я ищу что-то вроде этого (создания простых звуков) некоторое время назад и нашел эти библиотеки, которые сделали бы работу:

Я убежищем» Тем не менее, было время попробовать их сравнить. Получайте удовольствие от этого :)

Смежные вопросы