⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 22. 声音与音乐.txt

📁 本书介绍了在Microsoft Windows 98、Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
声音与音乐
 智能中国——游戏组  整理编译   
 

--------------------------------------------------------------------------------

在Microsoft Windows中,声音、音乐与视讯的综合运用是一个重要的进步。对多媒体的支持起源于1991年所谓的Microsoft Windows多媒体延伸功能(Multimedia Extensions to Microsoft Windows)。1992年,Windows 3.1的发布使得对多媒体的支持成为另一类API。最近几年,CD-ROM驱动器和声卡-在90年代初期还很少见-已成为新PC的标准配备。现在,几乎所有的人们都深信: 多媒体在很大程度上有益于Windows的可视化图形,从而使计算机摆脱了其只是处理数字和文字的机器的传统角色。

WINDOWS和多媒体


从某种意义上来说,多媒体就是透过与设备无关的函数呼叫来获得对各种硬件的存取。让我们首先看一下硬件,然后再看看Windows多媒体API的结构。

多媒体硬件


或许最常用的多媒体硬件就是波形声音设备,也就是平常所说的声卡。波形声音设备将麦克风的输入或其它声音输入转换为数字取样,并将其储存到内存或者储存到以.WAV为扩展名的磁盘文件中。波形声音设备还将波形转换回模拟声音,以便通过PC扩音器来播放。

声卡通常还包含MIDI设备。MIDI是符合工业标准的乐器数字化接口(Musical Instrument Digital Interface)。这类硬件播放音符以响应短的二进制命令消息。MIDI硬件通常还可以通过电缆连结到如音乐键盘等的MIDI输入设备上。通常,外部的MIDI合成器也能够添加到声卡上。

现在,大多数PC上的CD-ROM驱动器都具备播放普通音乐CD的能力。这就是平常所说的「CD声音」。来自波形声音设备、MIDI设备以及CD声音设备的输出,一般在使用者的控制下用「音量控制」程序混合在一起。

另外几种普遍的多媒体「设备」不需要额外的硬件。Windows视讯设备(也称作AVI视讯设备)播放扩展名为.AVI(audio-video interleave:声音视频插格)的电影或动画文件。「ActiveMovie控件」可以播放其它型态的电影,包括QuickTime和MPEG。PC上的显示卡需要特定的硬件来协助播放这些电影。

还有个别PC使用者使用某种Pioneer雷射影碟机或者Sony VISCA系列录放机。这些设备都有串行端口接口,因此可由PC软件来控制。某些显示卡具有一种称为「窗口影像(video in a window)」的功能,此功能允许一个外部的视讯信号与其它应用程序一起出现在Windows的屏幕上。这也可认为是一种多媒体设备。

API概述


在Windows中,API支持的多媒体功能主要分成两个集合。它们通常称为「低阶」和「高阶」界面。

低阶接口是一系列函数,这些函数以简短的说明性前缀开头,而且在/Platform SDK/Graphics and Multimedia Services/Multimedia Reference/Multimedia Functions(与高阶函数一起)中列出。

低阶的波形声音输入输出函数的前缀是waveIn和waveOut。我们将在本章看到这些函数。另外,本章还讨论用midiOut函数来控制MIDI输出设备。这些API还包括midiIn和midiStream函数。

本章还使用前缀为time的函数,这些函数允许设定一个高分辨率的定时器例程,其定时器的时间间隔速率最低能够到1毫秒。此程序主要用于播放MIDI音乐。其它几组函数包括声音压缩、视讯压缩以及动画和视讯序列,可惜的是本章不包括这些函数。

您还会注意到多媒体函数列表中七个带有前缀mci的函数,它们允许存取媒体控制接口(MCI:Media Control Interface)。这是一个高阶的开放接口,用于控制多媒体PC中所有的多媒体硬件。MCI包括所有多媒体硬件都共有的许多命令,因为多媒体的许多方面都以磁带录音机这类设备播放/记录方式为模型。您为输入或输出而「打开」一台设备,进而可以「录音」(对于输入)或者「播放」(对于输出),并且结束后可以「关闭」设备。

MCI本身分为两种形式。一种形式下,可以向MCI发送消息,这类似于Windows消息。这些消息包括位编码标记和C数据结构。另一种形式下,可以向MCI发送文字字符串。这个程序主要用于描述命令语言,此语言具有灵活的字符串处理函数,但支持呼叫Windows API的函数不多。字符串命令版的MCI还有利于交互研究和学习MCI,我们马上就举一个例子。MCI中的设备名称包括CD声音(cdaudio)、波形音响(waveaudio)、MIDI编曲器(sequencer)、影碟机(videodisc)、vcr、overlay(窗口中的模拟视频)、dat(digital audio tape:数字式录频磁带)以及数字视频(digitalvideo)。MCI设备分为「简单型」和「混合型」。简单型设备(如CD声音)不使用文件。混合型设备(如波形音响)则使用文件。使用波形音响时,这些文件的扩展名是.WAV。

存取多媒体硬件的另一种方法包括DirectX API,它超出了本书的范围。

另外两个高阶多媒体函数也值得一提:MessageBeep和PlaySound,它们在第三章有示范。MessageBeep播放「控制台」的「声音」中指定的声音。PlaySound可播放磁盘上、内存中或者作为资源加载的.WAV文件。本章的后面还会用到PlaySound函数。

用TESTMCI研究MCI


在Windows多媒体的早期,软件开发套件含有一个名为MCITEST的C程序,它允许程序写作者交谈式输入MCI命令并学习这些命令的工作方式。这个程序,至少是C语言版,显然已经消失了。因此,我又重新建立了它,即程序22-1所示的TESTMCI程序。虽然我不认为目前程序代码与旧的程序代码有什么区别,但现在的使用者接口还是依据以前的MCITEST程序,并且没有使用现在的程序代码。

程序22-1 TESTMCI 
        
TESTMCI.C
        
/*---------------------------------------------------------------------------
        
  TESTMCI.C -- MCI Command String Tester
        
                                                                (c) Charles Petzold, 1998
        
----------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include "resource.h"
        

#define ID_TIMER    1
        
BOOL CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM) ;
        
TCHAR szAppName [] = TEXT ("TestMci") ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                                PSTR szCmdLine, int iCmdShow)
        
{
        
           if (-1 == DialogBox (hInstance, szAppName, NULL, DlgProc))
        
           {
        
                  MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                                                        szAppName, MB_ICONERROR) ;
        
           }
        
           return 0 ;
        
}
        

BOOL CALLBACK DlgProc (    HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
           static HWND   hwndEdit ;
        
           int         iCharBeg, iCharEnd, iLineBeg, iLineEnd, iChar, iLine, iLength ;
        
           MCIERROR                      error ;
        
           RECT                          rect ;
        
           TCHAR                         szCommand [1024], szReturn [1024],
        
                                        szError [1024], szBuffer [32] ;
        

           switch (message)
        
           {
        
           case   WM_INITDIALOG:
        
                                         // Center the window on screen
        

                          GetWindowRect (hwnd, &rect) ;
        
                          SetWindowPos (hwnd, NULL,
        
                          (GetSystemMetrics (SM_CXSCREEN) - rect.right + rect.left) / 2,
        
                          (GetSystemMetrics (SM_CYSCREEN) - rect.bottom + rect.top) / 2,
        
                          0, 0, SWP_NOZORDER | SWP_NOSIZE) ;
        

                          hwndEdit = GetDlgItem (hwnd, IDC_MAIN_EDIT) ;
        
                          SetFocus (hwndEdit) ;
        
                          return FALSE ;
        

           case   WM_COMMAND:
        
                          switch (LOWORD (wParam))
        
                          {
        
                  case   IDOK:
        
                   // Find the line numbers corresponding to the selection
        

               SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iCharBeg,
        
                           (LPARAM) &iCharEnd) ;
        

                  iLineBeg = SendMessage (hwndEdit, EM_LINEFROMCHAR, iCharBeg, 0) ;
        
                  iLineEnd = SendMessage (hwndEdit, EM_LINEFROMCHAR, iCharEnd, 0) ;
        

                   // Loop through all the lines
        

                 for (iLine = iLineBeg ; iLine <= iLineEnd ; iLine++)
        
                          {
        
                    // Get the line and terminate it; ignore if blank
        

                   * (WORD *) szCommand = sizeof (szCommand) / sizeof (TCHAR) ;
        

                                         iLength = SendMessage (hwndEdit, EM_GETLINE, iLine,
        
                                                (LPARAM) szCommand) ;
        
                   szCommand [iLength] = '\0' ;
        

                                                                if (iLength == 0)
        
                                                               continue ;
        

            // Send the MCI command
        

            error =mciSendString (szCommand, szReturn,
        
            sizeof (szReturn) / sizeof (TCHAR), hwnd) ;
        

                       // Set the Return String field
        

           SetDlgItemText (hwnd, IDC_RETURN_STRING, szReturn) ;
        

                      // Set the Error String field (even if no error)
        

           mciGetErrorString (error, szError, sizeof (szError) / sizeof (TCHAR)) ;
        

                   SetDlgItemText (hwnd, IDC_ERROR_STRING, szError) ;
        
                           }
        
                           // Send the caret to the end of the last selected line
        

                           iChar  = SendMessage (hwndEdit, EM_LINEINDEX,  iLineEnd, 0) ;
        
                                         iChar += SendMessage (hwndEdit, EM_LINELENGTH, iCharEnd, 0) ;
        
                                         SendMessage (hwndEdit, EM_SETSEL, iChar, iChar) ;
        
             
        
                                         // Insert a carriage return/line feed combination
        

                          SendMessage (hwndEdit, EM_REPLACESEL, FALSE,
        
                               (LPARAM) TEXT ("\r\n")) ;
        
                                         SetFocus (hwndEdit) ;
        
                                         return TRUE ;
        

                          case   IDCANCEL:
        
                                                 EndDialog (hwnd, 0) ;
        
                                                 return TRUE ;
        
                          case   IDC_MAIN_EDIT:
        
                                                 if (HIWORD (wParam) == EN_ERRSPACE)
        
                                                {
        
                 MessageBox (hwnd, TEXT ("Error control out of space."),
        
                            szAppName, MB_OK | MB_ICONINFORMATION) ;
        
                return TRUE ;
        
                  }
        
                  break ;
        
                          }
        
                         break ;
        

           case   MM_MCINOTIFY:
        
                          EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_MESSAGE), TRUE) ;
        

                          wsprintf (szBuffer, TEXT ("Device ID = %i"), lParam) ;
        
                          SetDlgItemText (hwnd, IDC_NOTIFY_ID, szBuffer) ;
        
                         EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_ID), TRUE) ;
        

                         EnableWindow (GetDlgItem (hwnd, IDC_NOTIFY_SUCCESSFUL),
        
                                  wParam & MCI_NOTIFY_SUCCESSFUL) ;
        
        
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -