2008 December 12th Friday

   A new project will be started up.  From schedule, we have about twenty-eight days can be used.  If we can finish this project before the Spring Festival, that is good for our
customer and us.

waveOutOpen (&hWaveOut, wDeviceID, &waveformat, dwCallBack,
             dwCallBackData, dwFlags) ;

  You set the first argument to point to a variable of type HWAVEOUT ("handle to waveform audio output"). On return from the function, this variable will be set to a handle used
in subsequent waveform output calls.

  The second argument to waveOutOpen is a device ID. This allows the function to be used on machines that have multiple sound boards installed. The argument can range from 0 to
one less than the number of waveform output devices installed in the system. You can get the number of waveform output devices by calling waveOutGetNumDevs and find out about each
of them by calling waveOutGetDevCaps. If you wish to avoid this device interrogation, you can use the constant WAVE_MAPPER (defined as equalling -1) to select the device the user
as indicated as the Preferred Device in the Audio tab of the Multimedia applet of the Control Panel. Or the system could select another device if the preferred device can't handle
what you need to do and another device can.

  The third argument is a pointer to a WAVEFORMATEX structure. (More about this shortly.) The fourth argument is either a window handle or a pointer to a callback function in a dynamic-link
library. This argument indicates the window or callback function that receives the waveform output messages. If you use a callback function, you can specify program-defined data in
the fifth argument. The dwFlags argument can be set to either CALLBACK_WINDOW or CALLBACK_FUNCTION to indicate what the fourth argument is. You can also use the flag WAVE_FORMAT_QUERY
to check whether the device can be opened without actually opening it. A few other flags are available.

  The third argument to waveOutOpen is defined as a pointer to a structure of type WAVEFORMATEX, defined in MMSYSTEM.H as shown below:

typedef struct waveformat_tag
{
     WORD  wFormatTag ;        // waveform format = WAVE_FORMAT_PCM
     WORD  nChannels ;         // number of channels = 1 or 2
     DWORD nSamplesPerSec ;    // sample rate
     DWORD nAvgBytesPerSec ;   // bytes per second
     WORD  nBlockAlign ;       // block alignment
     WORD  wBitsPerSample ;    // bits per samples = 8 or 16
     WORD  cbSize ;            // 0 for PCM
}
WAVEFORMATEX, * PWAVEFORMATEX ;

  This is the structure you use to specify the sample rate (nSamplesPerSec), the sample size (wBitsPerSample), and whether you want monophonic or stereophonic sound (nChannels). Some of
the information in this structure may seem redundant, but the structure is designed for sampling methods other than PCM, in which case the last field is set to a nonzero value and other
information follows.

  For PCM, set nBlockAlign field to the product of nChannels and wBitsPerSample, divided by 8. This is the total number of bytes per sample. Set the nAvgBytesPerSec field to the product
of nSamplesPerSec and nBlockAlign.

An Introduction to MIDI Sequencing

  The low-level MIDI API consists of functions beginning with the prefix midiIn, for reading MIDI sequences coming from an external controller, and midiOut, for playing music on the internal
or external synthesizer. Despite the term "low-level," you don't need to know anything about the hardware interface of the MIDI board when using these functions.

  To open a MIDI output device in preparation for playing music, you call midiOutOpen:

error = midiOutOpen (&hMidiOut, wDeviceID, dwCallBack,
                     dwCallBackData, dwFlags) ;

  The function returns 0 if successful or an error code if not. If you've specified the function arguments correctly, an error will usually indicate that the MIDI device is already in use
by another program.

  The first argument is a pointer to a variable of type HMIDIOUT that receives a MIDI output handle for use in subsequent MIDI output functions. The second argument is the device ID. To use
one of the real MIDI devices, this argument can range from 0 to one less than the number returned from midiOutGetNumDevs. Or you can use MIDIMAPPER, which is defined in MMSYSTEM.H as -1. In most
cases, you'll probably set the last three arguments of midiOutOpen to NULL or 0.

  Once you open a MIDI output device and obtain the handle, you can begin sending MIDI messages to the device. You do this by calling

error = midiOutShortMsg (hMidiOut, dwMessage) ;

  The first parameter is the handle obtained from midiOutOpen. The second parameter is a 1-byte, 2-byte, or 3-byte MIDI message packed into a 32-bit DWORD. As I discussed earlier, MIDI messages
begin with a status byte, followed by 0, 1, or 2 bytes of data. The status byte forms the least significant byte of dwMessage, the first data byte is the next significant byte, and the second
data byte is the next. The most significant byte of dwMessage is 0.

  For example, to play a middle C (the note 0x3C) on MIDI channel 5 with a velocity of 0x7F, you need a 3-byte Note On message:

0x95 0x3C 0x7F

  The dwMessage parameter to midiOutShortMsg is 0x007F3C95.

  The three essential MIDI messages are Program Change (to change the instrument voice for a particular channel), Note On, and Note Off. After opening a MIDI output device, you should always begin
with a Program Change message and you should send an equal number of Note On and Note Off messages.

  When you're all done playing the music you want to play, you can reset the MIDI output device to make sure that all notes are turned off:

midiOutReset (hMidiOut) ;

  You can then close the device:

midiOutClose (hMidiOut) ;

  The midiOutOpen, midiOutShortMsg, midiOutReset, and midiOutClose functions are the four essential functions you need for using the low-level MIDI output API.

  So, let's play some music! The BACHTOCC program shown in Figure 22-10 plays the first measure of the toccata section of J. S. Bach's famous Toccata and Fugue in D Minor for organ.

  I wrote a dynamic array template in C++ language.  It is so useful to create a infinite array.

#include <string.h>
#include <iostream>

using namespace std;

class DynamicArrayException {
private:
    char what[256];
public:
    DynamicArrayException(){
        memset(what, 0, sizeof(what));
    }
   
    void setWhat(const char *msg){
        strcpy(what, msg);
    }
   
    char *getWhat(){
        return what;
    }
};

template <class T, int max>
class DynamicArray{
private:
    template <class V, int n>
    class Array{
    public:
        int seq_no;
        int count;  // the number of elements.
        Array<V, n> *next;
        Array<V, n> *prev;
        V elements[n];
    };
    Array<T, max> *head;
    Array<T, max> *current;
    Array<T, max> *tail;
   
    int total;  // the number of all elements in a dynamic array.
public:
    DynamicArray(){
        head = NULL;
        current = NULL;
        tail = NULL;
        total = 0;
       
        head = new Array<T, max>();
        if (head) {
            // initial the pointer of a node.
            head->next = NULL;
            head->prev = NULL;
            head->seq_no = 0;
            head->count = 0;
           
            // link a node.
            current = head;
            tail = head;          
        }
    }
   
    void append(T val) {
        // full
        if (tail->count >= max) {
            // add a node into the link.
            tail->next = new Array<T, max>();
tail->next->next = NULL;
tail->next->prev = NULL;

            tail->next->prev = tail;
            tail->next->seq_no = tail->seq_no + 1;
            tail = tail->next;
            tail->count = 0;
        }
       
        tail->elements[tail->count] = val;
        tail->count++;
        total++;
        current = tail;
    }
   
    void set(int index, T val) {
        if (index < 0) return;
       
        int step = (index / max) - current->seq_no;
        int pos = index % max;
       
        if (step > 0) {
            for (; step; step--)
                current = current->next;
        }
        else {
            for (; step; step++)
                current = current->prev;
        }
       
        current->elements[pos] = val;
    }
   
    T get(int index) {
        if (index < 0) {
            DynamicArrayException de;
char msg[] = "Invaild index";
            de.setWhat(msg);
            throw de;
        }
       
        int step = (index / max) - current->seq_no;
        int pos = index % max;
       
        if (step > 0) {
            for (; step; step--)
                current = current->next;
        }
        else {
            for (; step; step++)
                current = current->prev;
        }
       
        if (pos > current->count - 1) {
            DynamicArrayException e;
            e.setWhat("Invaild index");
            throw e;
        }
       
        return current->elements[pos];
    }
   
    ~DynamicArray(){
        while (head != NULL) {
current = head;
            head = head->next;
            delete current;
        }
head = NULL;
tail = NULL;
current = NULL;
        total = 0;
    }
};

int main(){
    DynamicArray<int, 10> narray;
    for (int i = 0; i < 12; i++)
        narray.append(i);
    for (int j = 11; j >= 0 ; j--){
        int n = narray.get(j);
        cout<<"[ "<<n<<" ]"<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值