/************************************************************************ * Copyright 2009-2011 Hikvision Digital Technology Co., Ltd. * FileName : audiotransfer.cpp * Description : audio transfer * Modification History : none * Version : V1.0 * Time : 2009-11,12 * Author : wanggongpu * Descrp : *************************************************************************/ #include "audiotransfer.h" #include #include #include #include "DemoPublic.h" #include "qtclientdemo.h" extern QtClientDemo* gqtclinetdemo; #ifndef _WIN32 extern unsigned int seg_isram; #endif /***************************************************************************** * * Routines to determine byte order (of this machine) and swap bytes * *****************************************************************************/ enum byte_order { order_unknown, order_bigEndian, order_littleEndian }; static enum byte_order DetermineByteOrder (void) { char s[sizeof (long) + 1]; union { long longval; char charval[sizeof (long)]; } probe; probe.longval = 0x41424344L; /* ABCD in ASCII */ strncpy (s, probe.charval, sizeof (long)); s[sizeof (long)] = '\0'; /* fprintf( stderr, "byte order is %s\n", s ); */ if (strcmp (s, "ABCD") == 0) return order_bigEndian; else if (strcmp (s, "DCBA") == 0) return order_littleEndian; else return order_unknown; } static void SwapBytesInWords (short *loc, int words) { int i; short thisval; char *dst, *src; src = (char *) &thisval; for (i = 0; i < words; i++) { thisval = *loc; dst = (char *) loc++; dst[0] = src[1]; dst[1] = src[0]; } } /***************************************************************************** * * Read in specified number of samples * *****************************************************************************/ int wave_get_samples (wave_info_t *wave_info, short int pcm[], int numSamples) { int samples_read; FILE *file = wave_info->soundfile; samples_read = fread (pcm, sizeof(short int), numSamples, file); /*if(samples_read < numSamples) { fseek(file, 0, SEEK_SET); samples_read = fread (pcm, sizeof(short int), numSamples, file); }*/ if (wave_info->byteswap) { SwapBytesInWords (pcm, samples_read); } return (samples_read/wave_info->channels); } /***************************************************************************** * * parse the wave header. * returns NULL if not open failed * returns a wave_info_t * if wave header successfully parsed. * needs to fill in : samplerate + channels * * POST: wave_info->soundfile is set to be at the start of the * PCM audio data * *****************************************************************************/ wave_info_t *wave_init (char *inPath, WaveFileHeader *waveheader) { unsigned char wave_header_buffer[40]; //HH fixed int wave_header_read = 0; int wave_header_stereo = -1; int wave_header_16bit = -1; unsigned long samplerate; enum byte_order NativeByteOrder = order_unknown; wave_info_t *wave_info = NULL; FILE *file; if ( (file = fopen(inPath, "rb"))==NULL) { DebugPrint("WAV: cannot open input file: %s\n", inPath); return(NULL); } /************** WAVE ************************/ /* Nick Burch */ /********************************************/ /* Wave File Headers: (Dec) */ /* 8-11 = "WAVE" */ /* 22 = Stereo / Mono */ /* 01 = mono, 02 = stereo */ /* 24 = Sampling Frequency */ /* 32 = Data Rate */ /* 01 = x1 (8bit Mono) */ /* 02 = x2 (8bit Stereo or */ /* 16bit Mono) */ /* 04 = x4 (16bit Stereo) */ /********************************************/ fread(waveheader,1 , sizeof(WaveFileHeader),file); fseek (file, 0, SEEK_SET); fread (wave_header_buffer, 1, 40, file); if (wave_header_buffer[8] == 'W' && wave_header_buffer[9] == 'A' && wave_header_buffer[10] == 'V' && wave_header_buffer[11] == 'E') { DebugPrint("Parsing Wave File Header\n"); if (NativeByteOrder == order_unknown) { NativeByteOrder = DetermineByteOrder (); if (NativeByteOrder == order_unknown) { DebugPrint ("byte order not determined\n"); fclose(file); return(NULL); } } if (NativeByteOrder == order_littleEndian) { #ifdef _WIN32 samplerate = *(unsigned long *) (&wave_header_buffer[24]); #else samplerate = *(unsigned int *) (&wave_header_buffer[24]); #endif } else { samplerate = wave_header_buffer[27] + (wave_header_buffer[26] << 8) + (wave_header_buffer[25] << 16) + (wave_header_buffer[24] << 24); } /* Wave File */ wave_header_read = 1; switch (samplerate) { case 44100: case 48000: case 32000: case 24000: case 22050: case 16000: DebugPrint (">>> %ld Hz sampling freq selected\n", samplerate); break; default: /* Unknown Unsupported Frequency */ DebugPrint (">>> Unknown samp freq %ld Hz in Wave Header\n", samplerate); DebugPrint (">>> Default 44.1 kHz samp freq selected\n"); samplerate = 44100; break; } if ((long) wave_header_buffer[22] == 1) { DebugPrint (">>> Input Wave File is Mono\n"); wave_header_stereo = 0; } if ((long) wave_header_buffer[22] == 2) { DebugPrint (">>> Input Wave File is Stereo\n"); wave_header_stereo = 1; } if ((long) wave_header_buffer[32] == 1) { DebugPrint (">>> Input Wave File is 8 Bit\n"); wave_header_16bit = 0; DebugPrint("Input File must be 16 Bit! Please Re-sample"); fclose(file); return(NULL); } if ((long) wave_header_buffer[32] == 2) { if (wave_header_stereo == 1) { DebugPrint(">>> Input Wave File is 8 Bit\n"); wave_header_16bit = 0; DebugPrint("Input File must be 16 Bit! Please Re-sample"); fclose(file); return(NULL); } else { fprintf(stderr, ">>> Input Wave File is 16 Bit\n" ); wave_header_16bit = 1; } } if ((long) wave_header_buffer[32] == 4) { /* fprintf(stderr, ">>> Input Wave File is 16 Bit\n" ); */ wave_header_16bit = 1; } /* should probably use the wave header to determine size here FIXME MFC Feb 2003 */ if (fseek (file, 44, SEEK_SET) != 0) { /* there's a way of calculating the size of the wave header. i'll just jump 44 to start with */ DebugPrint( "Could not seek to PCM sound data in \"%s\".\n", inPath); fclose(file); return(NULL); } // Successfully processed the wave header wave_info = (wave_info_t *)calloc(1, sizeof(wave_info_t)); wave_info->soundfile = file; if (wave_header_stereo == 1) wave_info->channels = 2; else wave_info->channels = 1; wave_info->samplerate = samplerate; // UNKNOWN. But we really should be able to work // it out. FIX THIS. MFC May03. wave_info->num_samples = -1; // Enable byte swap for big endian machines if (NativeByteOrder == order_bigEndian) wave_info->byteswap = 1; else wave_info->byteswap = 0; return(wave_info); } // not a wave file fclose(file); return(NULL); } /************************************************************************ * Function : AudioTransfer * Description : instructor * Input : none * Output : none * Return : none *************************************************************************/ AudioTransfer::AudioTransfer(QList * tree,QDialog *parent) : QDialog(parent) { ui.setupUi(this); m_qlistdevicetree =tree; for (int j=0;j<256;j++) { m_atuserid[j]=-1; } QList::iterator it; int i=0; for ( it = (*m_qlistdevicetree).begin(); it != (*m_qlistdevicetree).end(); ++it) { if ((*it).getUsrID()>=0) { m_atuserid[i]=(*it).getUsrID();//iºÍindexÒ»Ò»¶ÔÓ¦ i++; items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList((*it).getDeviceName()))); } } ui.treeWidget->insertTopLevelItems(0, items); connect(ui.treeWidget,SIGNAL(itemClicked(QTreeWidgetItem *, int)),this,SLOT(audioTransferDevice(QTreeWidgetItem *, int))); m_atindex = 0; m_talkmrhandle = -1; m_encodehandle = NULL; } /************************************************************************ * Function : ~AudioTransfer * Description : destructor * Input : none * Output : none * Return : none *************************************************************************/ AudioTransfer::~AudioTransfer() { } void AudioTransfer::audioTransferDevice(QTreeWidgetItem * item, int column) { QList::iterator it; int i=0; for ( it = (*m_qlistdevicetree).begin(),i=0; it != (*m_qlistdevicetree).end(); ++it) { if ((*it).getDeviceName()==item->text(column)) { m_atindex =i; break; } if ((*it).getUsrID()>=0) { i++; } } } void AudioTransfer::on_pushButton_browse_clicked() { QString directory = QFileDialog::getOpenFileName(this,\ tr("Find Update Files DIR and Filename"), QDir::currentPath()); if (!directory.isEmpty()) { ui.lineEdit_sendfilepath->insert(directory); } return; } /******************************************************************* Function: fVoiceDataCallBack Description: ÓïÒôת·¢»Øµ÷º¯Êý£¬ÓÃÓÚ»ñÈ¡É豸µÄÓïÒôÊý¾Ý Parameter: (IN) int lVoiceComHandle (IN) char *pRecvDataBuffer (IN) unsigned int dwBufSize (IN) unsigned char byAudioFlag (IN) void *pUser Return: HPR_OK--³É¹¦£¬HPR_ERROR--ʧ°Ü¡£ HPR_OK--³É¹¦£¬HPR_ERROR--ʧ°Ü¡£ **********************************************************************/ void __stdcall fVoiceDataCallBack(LONG lVoiceComHandle, char *pRecvDataBuffer, DWORD dwBufSize, BYTE byAudioFlag, void *pUser) { //´æÈë±í¸ñ QString currentdatetime = QDateTime::currentDateTime().toString(" yyyy-MM-dd hh:mm:ss"); QString datastring = QString(QLatin1String(pRecvDataBuffer)); QString handle = QString::number(lVoiceComHandle); QString totalsize = QString::number(dwBufSize); QString audioflag = QString::number(int(byAudioFlag)); QString userinfo = QString((char *)pUser); if (gqtclinetdemo->m_audiotransfer!=NULL) { QTableWidgetItem *currnettime = new QTableWidgetItem(currentdatetime); QTableWidgetItem *handleitem = new QTableWidgetItem(handle); QTableWidgetItem *sizeitem = new QTableWidgetItem(totalsize); QTableWidgetItem *flagitem = new QTableWidgetItem(audioflag); QTableWidgetItem *usrinfoitem = new QTableWidgetItem(userinfo); int row = gqtclinetdemo->m_audiotransfer->ui.tableWidget->rowCount(); gqtclinetdemo->m_audiotransfer->ui.tableWidget->insertRow(row); gqtclinetdemo->m_audiotransfer->ui.tableWidget->setItem(row, 0, currnettime); gqtclinetdemo->m_audiotransfer->ui.tableWidget->setItem(row, 1, handleitem); gqtclinetdemo->m_audiotransfer->ui.tableWidget->setItem(row, 2, sizeitem); gqtclinetdemo->m_audiotransfer->ui.tableWidget->setItem(row, 3, flagitem); gqtclinetdemo->m_audiotransfer->ui.tableWidget->setItem(row, 4, usrinfoitem); } //Send data to device after getting data. char pSendData[80]; memset(pSendData, 0, 80); NET_DVR_VoiceComSendData(lVoiceComHandle, pSendData, 80); } /******************************************************************* Function: AudioTransfer::on_pushButton_startmr_clicked Description: ¿ªÊ¼ÓïÒôת·¢btn Parameter: (IN) ÎÞ²ÎÊý Return: ÎÞ **********************************************************************/ void AudioTransfer::on_pushButton_startmr_clicked() { m_talkmrhandle = NET_DVR_StartVoiceCom_MR_V30(m_atuserid[m_atindex],1,fVoiceDataCallBack,0); if (m_talkmrhandle < 0) { QMessageBox::information(this,tr("NET_DVR_StartVoiceCom_MR_V30 error"), tr("m_atindex=%1 m_atuserid[m_atindex]=%2").arg(m_atindex).arg(m_atuserid[m_atindex])); } else { QMessageBox::information(this,tr("NET_DVR_StartVoiceCom_MR_V30 SUCC"), tr("NET_DVR_StartVoiceCom_MR_V30 SUCC")); ui.pushButton_startmr->setDisabled(1); ui.pushButton_stopmr->setDisabled(0); } } void AudioTransfer::on_pushButton_stopmr_clicked() { if (!NET_DVR_StopVoiceCom(m_talkmrhandle)) { QMessageBox::information(this,tr("NET_DVR_StopVoiceCom error"), tr("lasterror=%1").arg(NET_DVR_GetLastError())); } else { QMessageBox::information(this,tr("NET_DVR_StopVoiceCom SUCC"), tr("NET_DVR_StopVoiceCom SUCC")); ui.pushButton_stopmr->setDisabled(1); ui.pushButton_startmr->setDisabled(0); } } void AudioTransfer::on_pushButton_talkmrsend_clicked() { m_encodehandle = NET_DVR_InitG722Encoder(); if (m_encodehandle == (void*)-1) { QMessageBox::information(this,tr("NET_DVR_InitG722Encoder error"), tr("LAST_ERROR=%1").arg(NET_DVR_GetLastError())); } else { QMessageBox::information(this,tr("NET_DVR_InitG722Encoder SUCC"), tr("NET_DVR_InitG722Encoder SUCC")); } wave_info_t* para = (wave_info_t*)malloc(sizeof(wave_info_t)); WaveFileHeader header; short int pcmdata[640]; int i; para = wave_init(ui.lineEdit_sendfilepath->text().toLatin1().data(), &header); if ((para->channels!=1)&&(para->samplesize!=16)&&(para->samplerate!=16000)) { printf("the file is not correct for its parameters!\n"); QMessageBox::information(this,tr("ÒôƵÎļþ´íÎó"), tr("ÒôƵÎļþ²ÎÊý´íÎó")); return ; } unsigned char sendcontent[80]={0}; //int time =header.length/1280; //while (time>0) //{ i=wave_get_samples(para,pcmdata,640); //printf("time=%d\n",time); if (!NET_DVR_EncodeG722Frame(m_encodehandle, (unsigned char*)pcmdata, sendcontent)) { QMessageBox::information(this,tr("NET_DVR_EncodeG722Frame error"), tr("lasterror=%1").arg(NET_DVR_GetLastError())); } else { QMessageBox::information(this,tr("NET_DVR_EncodeG722Frame SUCC"), tr("NET_DVR_EncodeG722Frame SUCC")); } if (!NET_DVR_VoiceComSendData(m_talkmrhandle,(char*)sendcontent,80)) { QMessageBox::information(this,tr("NET_DVR_VoiceComSendData error"), tr("lasterror=%1").arg(NET_DVR_GetLastError())); } else { } //usleep(40000); //time -- ; //} NET_DVR_ReleaseG722Encoder(m_encodehandle); QMessageBox::information(this,tr("NET_DVR_VoiceComSendData SUCC"), tr("NET_DVR_VoiceComSendData SUCC")); } /************************************************************************ * Function : on_pushButton_exit_clicked * Description : Í˳ö½çÃæ * Input : none * Output : none * Return : none *************************************************************************/ void AudioTransfer::on_pushButton_exit_clicked() { close(); }