void prepareMicPlay()
{
	waveBlocks			= allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
	waveFreeBlockCount	= BLOCK_COUNT;
	waveCurrentBlock	= 0;
	InitializeCriticalSection(&waveCriticalSection);
}
MultiContainerBlock3D::MultiContainerBlock3D(MultiBlock3D const& rhs, Box3D subDomain, bool crop)
    : MultiBlock3D (
            intersect(rhs.getMultiBlockManagement(), subDomain, crop),
            rhs.getBlockCommunicator().clone(),
            rhs.getCombinedStatistics().clone() )
{
    allocateBlocks();
}
MultiContainerBlock3D::MultiContainerBlock3D(plint nx_, plint ny_, plint nz_)
    : MultiBlock3D (
            // Default envelope-width to 0
            defaultMultiBlockPolicy3D().getMultiBlockManagement(nx_,ny_,nz_, 0),
            defaultMultiBlockPolicy3D().getBlockCommunicator(),
            defaultMultiBlockPolicy3D().getCombinedStatistics() )
{
    allocateBlocks();
}
MultiContainerBlock3D::MultiContainerBlock3D (
        MultiBlockManagement3D const& multiBlockManagement_,
        CombinedStatistics* combinedStatistics_ )

    : MultiBlock3D(multiBlockManagement_,
                   defaultMultiBlockPolicy3D().getBlockCommunicator(),
                   combinedStatistics_)
{
    allocateBlocks();
}
/** 
 * \brief - open system default WAVE device
 * \param s - sydney audio stream handle
 * \return - completion status
 */ 
int openAudio(sa_stream_t *s) {
  int status;
  WAVEFORMATEX wfx;    
  UINT supported = FALSE;
		  
  status = allocateBlocks(s->blockSize, BLOCK_COUNT, &(s->waveBlocks));  
	HANDLE_WAVE_ERROR(status, "allocating audio buffer blocks");
  
  s->waveFreeBlockCount	= BLOCK_COUNT;
  s->waveCurrentBlock	= 0;  
  wfx.nSamplesPerSec	= (DWORD)s->rate;	/* sample rate */
  wfx.wBitsPerSample	= 16;				/* sample size */
  wfx.nChannels			= s->channels;	/* channels    */
  wfx.cbSize			= 0;				/* size of _extra_ info */
  wfx.wFormatTag		= WAVE_FORMAT_PCM;
  wfx.nBlockAlign		= (wfx.wBitsPerSample * wfx.nChannels) >> 3;
  wfx.nAvgBytesPerSec	= wfx.nBlockAlign * wfx.nSamplesPerSec;

  supported = waveOutOpen(NULL, WAVE_MAPPER, &wfx, (DWORD_PTR)0, (DWORD_PTR)0, 
				WAVE_FORMAT_QUERY);
  if (supported == MMSYSERR_NOERROR) { // audio device opened sucessfully 
    status = waveOutOpen((LPHWAVEOUT)&(s->hWaveOut), WAVE_MAPPER, &wfx, 
	  (DWORD_PTR)waveOutProc, (DWORD_PTR)s, CALLBACK_FUNCTION);
    if (status != MMSYSERR_NOERROR) {
      freeBlocks(s->waveBlocks);
      s->waveBlocks = NULL;
      HANDLE_WAVE_ERROR(status, "opening audio device for playback");
    }
  } 
  else if (supported == WAVERR_BADFORMAT) {
    printf("Requested format not supported.\n");
    // clean up the memory
    freeBlocks(s->waveBlocks);
    s->waveBlocks = NULL;
    return SA_ERROR_NOT_SUPPORTED;
  } 
  else {
    printf("Error opening default audio device.\n");
    // clean up the memory
    freeBlocks(s->waveBlocks);
    s->waveBlocks = NULL;
    return SA_ERROR_SYSTEM;
  }
  // create notification for data written to a device
  s->callbackEvent = CreateEvent(0, FALSE, FALSE, 0);
  // initialise critical section for operations on waveFreeBlockCound variable
  InitializeCriticalSection(&(s->waveCriticalSection));

  return SA_SUCCESS;
}
Beispiel #6
0
bool CWavePlay::Start(PWAVEFORMATEX pWavHead) 
{ 
	if (m_bPalyState) 
	{
		return false;
	}
	if (NULL==pWavHead)
	{
		return false;
	}
	//CloseDevice();
	_waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
	_nWaveFreeBlockCount = BLOCK_COUNT;
	_nWaveCurrentBlock   = 0;
	memcpy(&m_wavformex,pWavHead,sizeof(WAVEFORMATEX));
	m_wavformex.nBlockAlign     = (m_wavformex.wBitsPerSample * m_wavformex.nChannels) >> 3;
	m_wavformex.nAvgBytesPerSec = m_wavformex.nBlockAlign * m_wavformex.nSamplesPerSec;

	if(::waveOutOpen (0,0,&m_wavformex,0,0,WAVE_FORMAT_QUERY)) //WAVE_FORMAT_QUERY = $0001;{只是判断设备是否支持给定的格式, 并不打开}
	{ 
		//TRACE_ERR2("wave设备初始化失败~"); 
		return false; 
	} 

	//lphWaveOut: PHWaveOut;   {用于返回设备句柄的指针; 如果 dwFlags=WAVE_FORMAT_QUERY, 这里应是 nil}
	//uDeviceID: UINT;         {设备ID; 可以指定为: WAVE_MAPPER, 这样函数会根据给定的波形格式选择合适的设备}
	//lpFormat: PWaveFormatEx; {TWaveFormat 结构的指针; TWaveFormat 包含要申请的波形格式}
	//dwCallback: DWORD        {回调函数地址或窗口句柄; 若不使用回调机制, 设为 nil}
	//dwInstance: DWORD        {给回调函数的实例数据; 不用于窗口}
	//dwFlags: DWORD           {打开选项}
	if(waveOutOpen(&m_hWaveOut, WAVE_MAPPER, &m_wavformex, (DWORD_PTR)callback_waveOutProc, (DWORD)this, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) 
	{
		 //TRACE_ERR2("wave设备打开失败~"); 
		 return false;
	}
	m_bPalyState    = true;
	_nWaveCurrentBlock   = 0;
	return true;
} 
bool QAudioInputPrivate::open()
{
#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
    header = 0;
    if(buffer_size == 0) {
        // Default buffer size, 200ms, default period size is 40ms
        buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2;
        period_size = buffer_size/5;
    } else {
        period_size = buffer_size/5;
    }
#ifdef Q_OS_WINCE
    // For wince reduce size to 40ms for buffer size and 20ms period
    buffer_size = settings.sampleRate()*settings.channelCount()*(settings.sampleSize()/8)*0.04;
    period_size = buffer_size/2;
#endif
    timeStamp.restart();
    elapsedTimeOffset = 0;
    wfx.nSamplesPerSec = settings.frequency();
    wfx.wBitsPerSample = settings.sampleSize();
    wfx.nChannels = settings.channels();
    wfx.cbSize = 0;

    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    UINT_PTR devId = WAVE_MAPPER;

    WAVEINCAPS wic;
    unsigned long iNumDevs,ii;
    iNumDevs = waveInGetNumDevs();
    for(ii=0; ii<iNumDevs; ii++) {
        if(waveInGetDevCaps(ii, &wic, sizeof(WAVEINCAPS))
                == MMSYSERR_NOERROR) {
            QString tmp;
            tmp = QString::fromWCharArray(wic.szPname);
            if(tmp.compare(QLatin1String(m_device)) == 0) {
                devId = ii;
                break;
            }
        }
    }

    if(waveInOpen(&hWaveIn, devId, &wfx,
                  (DWORD_PTR)&waveInProc,
                  (DWORD_PTR) this,
                  CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        qWarning("QAudioInput: failed to open audio device");
        return false;
    }
    waveBlocks = allocateBlocks(period_size, buffer_size/period_size);

    if(waveBlocks == 0) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        qWarning("QAudioInput: failed to allocate blocks. open failed");
        return false;
    }

    mutex.lock();
    waveFreeBlockCount = buffer_size/period_size;
    mutex.unlock();

    waveCurrentBlock = 0;

    for(int i=0; i<buffer_size/period_size; i++) {
        result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR));
        if(result != MMSYSERR_NOERROR) {
            qWarning("QAudioInput: failed to setup block %d,err=%d",i,result);
            errorState = QAudio::OpenError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            return false;
        }
    }
    result = waveInStart(hWaveIn);
    if(result) {
        qWarning("QAudioInput: failed to start audio input");
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        return false;
    }
    timeStampOpened.restart();
    elapsedTimeOffset = 0;
    totalTimeValue = 0;
    errorState  = QAudio::NoError;
    return true;
}
void UDPread(UDPinfo *UI, int filesize)
{
	WSABUF UDPread;
	int bytesRecv = 0;
	DWORD flags = 0;
	int err;
	WAVEHDR* waveBlocks;
	FILE *fp;
	WAVEFORMATEX wfx;
	wavheader WH;
	HWAVEOUT hWaveOut;
	char data[BUFSIZE];
	int i = 0;

	UDPread.buf = (char *) malloc (BUFSIZE);
	UDPread.len = BUFSIZE;


	waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
	waveFreeBlockCount = BLOCK_COUNT;
	waveCurrentBlock = 0;
	InitializeCriticalSection(&waveCriticalSection);

	fp = wavOpen(&WH);

	wfx.nSamplesPerSec = WH.sampleRate;
	wfx.wBitsPerSample = 16;
	wfx.nChannels = 2;
	wfx.cbSize = 0;
	wfx.wFormatTag = WAVE_FORMAT_PCM;
	wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3;
	wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

	
	if((err = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx,(DWORD_PTR)waveOutProc, (DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
	{
		fprintf(stdout, "unable to open wave mapper device");
		fprintf(stdout, "%d", err);
		ExitProcess(1);
	}
	while(bytesRecv < filesize)
	{
		if(recvfrom(UI->sd, UDPread.buf, BUFSIZE, flags,NULL,NULL) == SOCKET_ERROR)
		{
			err = WSAGetLastError();
			if(err != ERROR_IO_PENDING)
			{
				// error during read
			}
		}
	

		
		memcpy(data,UDPread.buf, BUFSIZE);
		
		writeAudio(hWaveOut, data, BUFSIZE, waveBlocks, waveCriticalSection);
		bytesRecv += BUFSIZE;
	}
	/*
	 * unprepare any blocks that are still prepared
	 */
	for(i = 0; i < waveFreeBlockCount; i++) 
	{
		if(waveBlocks[i].dwFlags & WHDR_PREPARED)
		{
			waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR));
		}
	}
	DeleteCriticalSection(&waveCriticalSection);
	freeBlocks(waveBlocks);
	waveOutClose(hWaveOut);


	
}
/*-----------------------------------------------------------------------------
--	FUNCTION:		receiveStream
--
--	DATE:			2009-04-06
--
--	REVISIONS:		2009-04-06 - Jaymz, Took out the TCP connection stuff since
--								 we already have that at this point. Also added
--								 a parameter WPARAM sd, which is the socket
--								 from which we are receiving the data.
--							   - Jaymz, Miscellaneous code touch-ups (mainly
--								 formatting and removing of test printf()'s)
--
--	DESIGNER(S):	David Overton
--	PROGRAMMER(S):	David Overton, Jaymz Boilard, Steffen L. Norgren
--
--	INTERFACE:		receiveStream(LPVOID iValue)
--
--	RETURNS:		void
--
--	NOTES: The main function to receive a UDP stream of data and process
--	that information.
-----------------------------------------------------------------------------*/
DWORD WINAPI receiveStream(LPVOID iValue)
{
	WAVEFORMATEX	wfx;
	char			buffer[BLOCK_SIZE]; /* intermediate buffer for reading */
	int				i, n, remote_len;
	DWORD			outBytes = 0;
	char			* play_byte = "1";
	BOOL			firstRun = TRUE;

	remote_len = sizeof(udp_remote);

	/* initialise the module variables */
	waveBlocks			= allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
	waveFreeBlockCount	= BLOCK_COUNT;
	waveCurrentBlock	= 0;
	InitializeCriticalSection(&waveCriticalSection);
	
	/* playback loop - read from socket */
	while (TRUE) 
	{
		if (ci.request != MULTI_STREAM) {
			/* send play signal */
			sendto(ci.udpSocket, play_byte, sizeof(play_byte), 0, (struct sockaddr *)&udp_remote, remote_len);
		}

		if ((n = recvfrom(ci.udpSocket, buffer, sizeof(buffer), 0, (struct sockaddr *)&udp_remote, &remote_len)) <= 0)
		{
			waveOutClose(hWaveOut);
			ExitThread(0);
		}

		/* first 4 bytes in a file, so set the header information */
		if(strncmp(buffer, "RIFF", 4) == 0)
		{
			memcpy(&wfx, buffer+20, sizeof(wfx));

			if (ci.request != MULTI_STREAM || firstRun == TRUE) {
				waveOutClose(hWaveOut);
			
				if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc,
					(DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
				{
						MessageBox(NULL, "Unable to open mapper device.", "Error", MB_OK);
						ExitProcess(1);
				}
				firstRun = FALSE;
			}
		}

		if(n == 0)
			break;
		else if(n < sizeof(buffer) && n != WAVE_HEAD_SIZE)
		{
			memset(buffer + n, 0, sizeof(buffer) - n);
			writeAudio(buffer, n);
			break;
		}

		writeAudio(buffer, n);
	}

	/* wait for all blocks to complete */
	while(waveFreeBlockCount < BLOCK_COUNT)
		Sleep(10);

	/* unprepare any blocks that are still prepared */
	for(i = 0; i < waveFreeBlockCount; i++)
	{
		if(waveBlocks[i].dwFlags & WHDR_PREPARED)
			waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR));
	}
	DeleteCriticalSection(&waveCriticalSection);
	freeBlocks(waveBlocks);
	waveOutClose(hWaveOut);
	streamInProgress = FALSE;
	ExitThread(0);
}
MultiContainerBlock3D::MultiContainerBlock3D(MultiContainerBlock3D const& rhs)
    : MultiBlock3D(rhs)
{
    allocateBlocks();
}
Beispiel #11
0
bool QAudioOutputPrivate::open()
{
#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
    if (!(settings.frequency() >= 8000 && settings.frequency() <= 48000)) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        qWarning("QAudioOutput: open error, frequency out of range.");
        return false;
    }
    if(buffer_size == 0) {
        // Default buffer size, 200ms, default period size is 40ms
        buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2;
	period_size = buffer_size/5;
    } else {
        period_size = buffer_size/5;
    }
    waveBlocks = allocateBlocks(period_size, buffer_size/period_size);

    EnterCriticalSection(&waveOutCriticalSection);
    waveFreeBlockCount = buffer_size/period_size;
    LeaveCriticalSection(&waveOutCriticalSection);

    waveCurrentBlock = 0;

    if(audioBuffer == 0)
        audioBuffer = new char[buffer_size];

    timeStamp.restart();
    elapsedTimeOffset = 0;

    wfx.nSamplesPerSec = settings.frequency();
    wfx.wBitsPerSample = settings.sampleSize();
    wfx.nChannels = settings.channels();
    wfx.cbSize = 0;

    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    UINT_PTR devId = WAVE_MAPPER;

    WAVEOUTCAPS woc;
    unsigned long iNumDevs,ii;
    iNumDevs = waveOutGetNumDevs();
    for(ii=0;ii<iNumDevs;ii++) {
        if(waveOutGetDevCaps(ii, &woc, sizeof(WAVEOUTCAPS))
	    == MMSYSERR_NOERROR) {
	    QString tmp;
	    tmp = QString((const QChar *)woc.szPname);
            if(tmp.compare(QLatin1String(m_device)) == 0) {
	        devId = ii;
		break;
	    }
	}
    }

    if(waveOutOpen(&hWaveOut, devId, &wfx,
                (DWORD_PTR)&waveOutProc,
                (DWORD_PTR) this,
                CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        qWarning("QAudioOutput: open error");
        return false;
    }

    totalTimeValue = 0;
    timeStampOpened.restart();
    elapsedTimeOffset = 0;

    errorState = QAudio::NoError;
    if(pullMode) {
        deviceState = QAudio::ActiveState;
        QTimer::singleShot(10, this, SLOT(feedback()));
    } else
        deviceState = QAudio::IdleState;

    return true;
}
Beispiel #12
0
bool QAudioOutputPrivate::open()
{
#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif

    period_size = 0;

    if (!settings.isValid()) {
        qWarning("QAudioOutput: open error, invalid format.");
    } else if (settings.channels() <= 0) {
        qWarning("QAudioOutput: open error, invalid number of channels (%d).",
                 settings.channels());
    } else if (settings.sampleSize() <= 0) {
        qWarning("QAudioOutput: open error, invalid sample size (%d).",
                 settings.sampleSize());
    } else if (settings.frequency() < 8000 || settings.frequency() > 48000) {
        qWarning("QAudioOutput: open error, frequency out of range (%d).", settings.frequency());
    } else if (buffer_size == 0) {
        // Default buffer size, 200ms, default period size is 40ms
        buffer_size
                = (settings.frequency()
                * settings.channels()
                * settings.sampleSize()
                + 39) / 40;
        period_size = buffer_size / 5;
    } else {
        period_size = buffer_size / 5;
    }

    if (period_size == 0) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        return false;
    }

    waveBlocks = allocateBlocks(period_size, buffer_size/period_size);

    mutex.lock();
    waveFreeBlockCount = buffer_size/period_size;
    mutex.unlock();

    waveCurrentBlock = 0;

    if(audioBuffer == 0)
        audioBuffer = new char[buffer_size];

    timeStamp.restart();
    elapsedTimeOffset = 0;

    wfx.nSamplesPerSec = settings.frequency();
    wfx.wBitsPerSample = settings.sampleSize();
    wfx.nChannels = settings.channels();
    wfx.cbSize = 0;

    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    UINT_PTR devId = WAVE_MAPPER;

    WAVEOUTCAPS woc;
    unsigned long iNumDevs,ii;
    iNumDevs = waveOutGetNumDevs();
    for(ii=0;ii<iNumDevs;ii++) {
        if(waveOutGetDevCaps(ii, &woc, sizeof(WAVEOUTCAPS))
	    == MMSYSERR_NOERROR) {
	    QString tmp;
	    tmp = QString((const QChar *)woc.szPname);
            if(tmp.compare(QLatin1String(m_device)) == 0) {
	        devId = ii;
		break;
	    }
	}
    }

    if ( settings.channels() <= 2) {
        if(waveOutOpen(&hWaveOut, devId, &wfx,
                    (DWORD_PTR)&waveOutProc,
                    (DWORD_PTR) this,
                    CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
            errorState = QAudio::OpenError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            qWarning("QAudioOutput: open error");
            return false;
        }
    } else {
        WAVEFORMATEXTENSIBLE wfex;
        wfex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
        wfex.Format.nChannels = settings.channels();
        wfex.Format.wBitsPerSample = settings.sampleSize();
        wfex.Format.nSamplesPerSec = settings.frequency();
        wfex.Format.nBlockAlign = wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
        wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*wfex.Format.nBlockAlign;
        wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
        static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
             0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
        wfex.SubFormat=_KSDATAFORMAT_SUBTYPE_PCM;
        wfex.Format.cbSize=22;

        wfex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
        if (settings.channels() >= 4)
            wfex.dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
        if (settings.channels() >= 6)
            wfex.dwChannelMask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY;
        if (settings.channels() == 8)
            wfex.dwChannelMask |= SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;

        if(waveOutOpen(&hWaveOut, devId, &wfex.Format,
                    (DWORD_PTR)&waveOutProc,
                    (DWORD_PTR) this,
                    CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
            errorState = QAudio::OpenError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            qWarning("QAudioOutput: open error");
            return false;
        }
    }

    totalTimeValue = 0;
    timeStampOpened.restart();
    elapsedTimeOffset = 0;

    errorState = QAudio::NoError;
    if(pullMode) {
        deviceState = QAudio::ActiveState;
        QTimer::singleShot(10, this, SLOT(feedback()));
    } else
        deviceState = QAudio::IdleState;

    return true;
}
bool QAudioOutputPrivate::open()
{
#ifdef DEBUG_AUDIO
    QTime now(QTime::currentTime());
    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif

    period_size = 0;

    if (!settings.isValid()) {
        qWarning("QAudioOutput: open error, invalid format.");
    } else if (settings.channelCount() <= 0) {
        qWarning("QAudioOutput: open error, invalid number of channels (%d).",
                 settings.channelCount());
    } else if (settings.sampleSize() <= 0) {
        qWarning("QAudioOutput: open error, invalid sample size (%d).",
                 settings.sampleSize());
    } else if (settings.frequency() < 8000 || settings.frequency() > 96000) {
        qWarning("QAudioOutput: open error, frequency out of range (%d).", settings.frequency());
    } else if (buffer_size == 0) {
        // Default buffer size, 200ms, default period size is 40ms
        buffer_size
                = (settings.frequency()
                * settings.channelCount()
                * settings.sampleSize()
                + 39) / 40;
        period_size = buffer_size / 5;
    } else {
        period_size = buffer_size / 5;
    }

    if (period_size == 0) {
        errorState = QAudio::OpenError;
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
        return false;
    }

    waveBlocks = allocateBlocks(period_size, buffer_size/period_size);

    mutex.lock();
    waveFreeBlockCount = buffer_size/period_size;
    mutex.unlock();

    waveCurrentBlock = 0;

    if(audioBuffer == 0)
        audioBuffer = new char[buffer_size];

    timeStamp.restart();
    elapsedTimeOffset = 0;

    wfx.nSamplesPerSec = settings.frequency();
    wfx.wBitsPerSample = settings.sampleSize();
    wfx.nChannels = settings.channels();
    wfx.cbSize = 0;

    bool surround = false;

    if (settings.channels() > 2)
        surround = true;

    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    QDataStream ds(&m_device, QIODevice::ReadOnly);
    quint32 deviceId;
    ds >> deviceId;

    if (!surround) {
        if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfx,
                    (DWORD_PTR)&waveOutProc,
                    (DWORD_PTR) this,
                    CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
            errorState = QAudio::OpenError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            qWarning("QAudioOutput: open error");
            return false;
        }
    } else {
        WAVEFORMATEXTENSIBLE wfex;
        wfex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
        wfex.Format.nChannels = settings.channels();
        wfex.Format.wBitsPerSample = settings.sampleSize();
        wfex.Format.nSamplesPerSec = settings.frequency();
        wfex.Format.nBlockAlign = wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
        wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*wfex.Format.nBlockAlign;
        wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
        static const GUID _KSDATAFORMAT_SUBTYPE_PCM = {
             0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
        wfex.SubFormat=_KSDATAFORMAT_SUBTYPE_PCM;
        wfex.Format.cbSize=22;

        wfex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
        if (settings.channels() >= 4)
            wfex.dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
        if (settings.channels() >= 6)
            wfex.dwChannelMask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY;
        if (settings.channels() == 8)
            wfex.dwChannelMask |= SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;

        if (waveOutOpen(&hWaveOut, UINT_PTR(deviceId), &wfex.Format,
                    (DWORD_PTR)&waveOutProc,
                    (DWORD_PTR) this,
                    CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
            errorState = QAudio::OpenError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            qWarning("QAudioOutput: open error");
            return false;
        }
    }

    totalTimeValue = 0;
    timeStampOpened.restart();
    elapsedTimeOffset = 0;

    errorState = QAudio::NoError;
    if(pullMode) {
        deviceState = QAudio::ActiveState;
        QTimer::singleShot(10, this, SLOT(feedback()));
    } else
        deviceState = QAudio::IdleState;

    return true;
}