Update contrib.
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\multimedia\t_soundwav.cpp
15 // Record wav to a file "t_soundwav filename [rate] [channels] [seconds]" where filename does not exist.
16 // Play a wav file "t_soundwav filename" where filename exists.
21 @file Shared chunk sound driver WAV file player and recorder utility.
26 #include <e32def_private.h>
27 #include "t_soundutils.h"
30 #define CHECK(aValue) {Test(aValue);}
31 #define CHECK_NOERROR(aValue) { TInt v=(aValue); if(v) { Test.Printf(_L("Error value = %d\n"),v); Test(EFalse,__LINE__); }}
32 #define CHECK_EQUAL(aValue1,aValue2) { TInt v1=(aValue1); TInt v2=(aValue2); if(v1!=v2) { Test.Printf(_L("Error value = %d\n"),v1); Test(EFalse,__LINE__); }}
34 _LIT(KSndLddFileName,"ESOUNDSC.LDD");
35 _LIT(KSndPddFileName,"SOUNDSC.PDD");
37 RTest Test(_L("T_SOUNDWAV"));
38 RSoundSc TxSoundDevice;
39 RSoundSc RxSoundDevice;
41 TSoundFormatsSupportedV02Buf RecordCapsBuf;
42 TSoundFormatsSupportedV02Buf PlayCapsBuf;
43 TCurrentSoundFormatV02Buf PlayFormatBuf;
44 TCurrentSoundFormatV02Buf RecordFormatBuf;
46 TBuf<256> CommandLine;
50 // This is the WAV header structure used for playing and recording files
54 char ckID[4]; // chunk id 'RIFF'
55 TUint32 ckSize; // chunk size
56 char wave_ckID[4]; // wave chunk id 'WAVE'
57 char fmt_ckID[4]; // format chunk id 'fmt '
58 TUint32 fmt_ckSize; // format chunk size
59 TUint16 formatTag; // format tag currently pcm
60 TUint16 nChannels; // number of channels
61 TUint32 nSamplesPerSec; // sample rate in hz
62 TUint32 nAvgBytesPerSec; // average bytes per second
63 TUint16 nBlockAlign; // number of bytes per sample
64 TUint16 nBitsPerSample; // number of bits in a sample
65 char data_ckID[4]; // data chunk id 'data'
66 TUint32 data_ckSize; // length of data chunk
69 LOCAL_C TInt SamplesPerSecondToRate(TInt aRateInSamplesPerSecond,TSoundRate& aRate)
71 switch (aRateInSamplesPerSecond)
73 case 7350: aRate=ESoundRate7350Hz; break;
74 case 8000: aRate=ESoundRate8000Hz; break;
75 case 8820: aRate=ESoundRate8820Hz; break;
76 case 9600: aRate=ESoundRate9600Hz; break;
77 case 11025: aRate=ESoundRate11025Hz; break;
78 case 12000: aRate=ESoundRate12000Hz; break;
79 case 14700: aRate=ESoundRate14700Hz; break;
80 case 16000: aRate=ESoundRate16000Hz; break;
81 case 22050: aRate=ESoundRate22050Hz; break;
82 case 24000: aRate=ESoundRate24000Hz; break;
83 case 29400: aRate=ESoundRate29400Hz; break;
84 case 32000: aRate=ESoundRate32000Hz; break;
85 case 44100: aRate=ESoundRate44100Hz; break;
86 case 48000: aRate=ESoundRate48000Hz; break;
87 default: return(KErrArgument);
92 LOCAL_C TInt RecordBufferSizeInBytes(TCurrentSoundFormatV02& aFormat)
94 switch (aFormat.iRate)
96 case ESoundRate7350Hz: return(8192);
97 case ESoundRate8000Hz: return(8192);
98 case ESoundRate8820Hz: return(12288);
99 case ESoundRate9600Hz: return(12288);
100 case ESoundRate11025Hz: return(12288);
101 case ESoundRate12000Hz: return(12288);
102 case ESoundRate14700Hz: return(12288);
103 case ESoundRate16000Hz: return(12288);
104 case ESoundRate22050Hz: return(16384);
105 case ESoundRate24000Hz: return(16384);
106 case ESoundRate29400Hz: return(24576);
107 case ESoundRate32000Hz: return(24576);
108 case ESoundRate44100Hz: return(32768);
109 case ESoundRate48000Hz: return(32768);
110 default: return(32768);
118 Test.Start(_L("Load sound PDD"));
119 r=User::LoadPhysicalDevice(KSndPddFileName);
125 CHECK(r==KErrNone || r==KErrAlreadyExists);
127 Test.Next(_L("Load sound LDD"));
128 r=User::LoadLogicalDevice(KSndLddFileName);
129 CHECK(r==KErrNone || r==KErrAlreadyExists);
135 LOCAL_C TInt WavPlay()
139 // Parse the commandline and get a filename to use
141 TFileName thisfile=RProcess().FileName();
142 TPtrC token=l.NextToken();
143 if (token.MatchF(thisfile)==0)
144 token.Set(l.NextToken());
146 if (token.Length()==0)
148 // No args, skip to end
149 Test.Printf(_L("Invalid configuration\r\n"));
150 return(KErrArgument);
153 Test.Next(_L("Play Wav file"));
155 // Assume that the argument is a WAV filename
156 TFileName wavFilename=token;
159 r = source.Open(Fs,wavFilename,EFileRead);
162 Test.Printf(_L("Open failed(%d)\r\n"), r);
166 // Read the pcm header
168 TPtr8 headerDes((TUint8 *)&header,sizeof(struct WAVEheader),sizeof(struct WAVEheader));
169 r = source.Read(headerDes);
175 Test.Printf(_L("Header Read %d bytes\r\n"),headerDes.Size());
177 if (headerDes.Size() != sizeof(struct WAVEheader)) // EOF
179 Test.Printf(_L("Couldn't read a header(%d bytes)\r\n"),headerDes.Size());
184 Test.Printf(_L("Header rate:%d channels:%d tag:%d bits:%d (%d bytes/s) align %d datalen:%d fmt_ckSize:%d ckSize:%d\n"),
185 header.nSamplesPerSec, header.nChannels, header.formatTag, header.nBitsPerSample,
186 header.nAvgBytesPerSec, header.nBlockAlign, header.data_ckSize, header.fmt_ckSize, header.ckSize);
188 if (header.formatTag != 1) // not pcm
190 Test.Printf(_L("Format not PCM(%d)\r\n"),header.formatTag);
192 return(KErrNotSupported);
195 if (header.nBitsPerSample != 16) // not 16 bit
197 Test.Printf(_L("Format not 16 bit PCM(%d bits)\r\n"),header.nBitsPerSample);
199 return(KErrNotSupported);
203 if (SamplesPerSecondToRate(header.nSamplesPerSec,rate)!=KErrNone)
205 Test.Printf(_L("Format specifies a rate not supported(%d)\r\n"),header.nSamplesPerSec);
207 return(KErrNotSupported);
210 TxSoundDevice.AudioFormat(PlayFormatBuf); // Read back the current setting which must be valid.
211 PlayFormatBuf().iChannels = header.nChannels;
212 PlayFormatBuf().iRate = rate;
213 PlayFormatBuf().iEncoding = ESoundEncoding16BitPCM;
215 // Set the play buffer configuration.
216 TInt bufSize=BytesPerSecond(PlayFormatBuf())/8; // Large enough to hold 1/8th second of data.
217 bufSize&=~(header.nBlockAlign-1); // Keep the buffer length a multiple of the bytes per sample (assumes 16bitPCM, 1 or 2 chans).
218 if (PlayCapsBuf().iRequestMinSize)
219 bufSize&=~(PlayCapsBuf().iRequestMinSize-1); // Keep the buffer length valid for the driver.
220 TTestSharedChunkBufConfig bufferConfig;
221 bufferConfig.iNumBuffers=3;
222 bufferConfig.iBufferSizeInBytes=bufSize;
223 bufferConfig.iFlags=0;
224 PrintBufferConf(bufferConfig,Test);
225 TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
226 r=TxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
229 Test.Printf(_L("Buffer configuration not supported(%d)\r\n"),r);
233 TxSoundDevice.GetBufferConfig(bufferConfigBuf); // Read back the configuration - to get the buffer offsets
234 CHECK(bufferConfig.iBufferSizeInBytes==bufSize);
236 // Set the audio play configuration.
237 TxSoundDevice.SetVolume(KSoundMaxVolume - (KSoundMaxVolume / 4)); // set volume to 75%
238 PrintConfig(PlayFormatBuf(),Test);
239 r=TxSoundDevice.SetAudioFormat(PlayFormatBuf);
242 Test.Printf(_L("Format not supported\r\n"));
247 TxSoundDevice.ResetBytesTransferred();
249 TInt32 bytesToPlay = header.data_ckSize;
251 starttime.HomeTime();
253 TRequestStatus stat[3];
257 tPtr[i]=new TPtr8(NULL,0);
260 startTime.HomeTime();
262 // Start off by issuing a play request for each buffer (assuming that the file is long enough). Use the full size
264 TInt stillToRead=bytesToPlay;
265 TInt stillNotPlayed=bytesToPlay;
267 for (i=0 ; i<3 ; i++)
269 // Setup the descriptor for reading in the data from the file.
270 tPtr[i]->Set(chunk.Base()+bufferConfig.iBufferOffsetList[i],0,bufSize);
272 // If there is still data to read to play then read this into the descriptor
273 // and then write it to the driver.
276 r=source.Read(*tPtr[i],Min(stillToRead,bufSize));
279 Test.Printf(_L("Initial file read error(%d)\r\n"),r);
284 stillToRead-=tPtr[i]->Length();
285 flags=(stillToRead>0)?0:KSndFlagLastSample;
286 TxSoundDevice.PlayData(stat[i],bufferConfig.iBufferOffsetList[i],tPtr[i]->Length(),flags);
289 stat[i]=KRequestPending;
294 // Wait for any one of the outstanding play requests to complete.
295 User::WaitForAnyRequest();
298 currentTime.HomeTime();
299 TInt64 elapsedTime = currentTime.Int64()-startTime.Int64(); // us
300 TTimeIntervalMicroSecondsBuf timePlayedBuf;
301 if(TxSoundDevice.TimePlayed(timePlayedBuf) == KErrNone)
303 // Compare TimePlayed with the actual elapsed time. They should be different, but not drift apart too badly...
304 TInt32 offset = TInt32(elapsedTime - timePlayedBuf().Int64());
305 Test.Printf(_L("\telapsedTime - TimePlayed = %d ms\n"), offset/1000);
308 // Work out which buffer this applies to
309 for (i=0 ; i<3 ; i++)
311 if (stat[i]!=KRequestPending)
316 Test.Printf(_L("I/O error\r\n"));
322 // Check that the transfer was succesful and whether we have now played all the file.
323 if (stat[i]!=KErrNone)
325 Test.Printf(_L("Play error(%d)\r\n"),stat[i].Int());
328 return(stat[i].Int());
330 Test.Printf(_L("Played %d bytes(%d) - %d\r\n"),tPtr[i]->Length(),i,stat[i].Int());
331 stillNotPlayed-=tPtr[i]->Length();
332 CHECK(stillNotPlayed>=0);
336 // Still more to be played so read the next part of the file into the descriptor for this
337 // buffer and then write it to the driver.
340 TInt len=Min(stillToRead,bufSize);
342 // If we've got to the end of the file and the driver is particular about the request length then
343 // zero fill the entire buffer so we can play extra zeros after the last sample from the file.
344 if (len<bufSize && PlayCapsBuf().iRequestMinSize)
345 tPtr[i]->FillZ(bufSize);
347 // Read the next part of the file
348 r=source.Read(*tPtr[i],len); // This will alter the length of the descriptor
351 Test.Printf(_L("File read error(%d)\r\n"),r);
356 stillToRead-=tPtr[i]->Length();
358 // If we've got to the end of the file and the driver is particular about the request length then
359 // round up the length to the next valid boundary. This is OK since we zero filled.
360 if (tPtr[i]->Length() < bufSize && PlayCapsBuf().iRequestMinSize)
362 TUint m=PlayCapsBuf().iRequestMinSize-1;
363 len=(tPtr[i]->Length() + m) & ~m;
366 // Write it to the driver.
367 flags=(stillToRead>0)?0:KSndFlagLastSample;
368 TxSoundDevice.PlayData(stat[i],bufferConfig.iBufferOffsetList[i],len,flags);
371 stat[i]=KRequestPending;
374 // Delete all the variables again.
375 for (i=0 ; i<3 ; i++)
381 Test.Printf(_L("Done playing\r\n"));
382 Test.Printf(_L("Bytes played = %d\r\n"),TxSoundDevice.BytesTransferred());
383 Test.Printf(_L("Delta time = %d\r\n"),endtime.Int64()-starttime.Int64());
390 LOCAL_C TInt WavRecord()
392 // Parse the commandline and get a filename to use
394 TParse destinationName;
395 if (destinationName.SetNoWild(l.NextToken(),0,0)!=KErrNone)
397 Test.Printf(_L("No arg, skipping\r\n"));
398 return(KErrArgument);
400 Test.Next(_L("Record Wav file"));
402 // Open the file for writing
405 r = destination.Replace(Fs,destinationName.FullName(),EFileWrite);
408 Test.Printf(_L("Open file for write failed(%d)\n"), r);
411 Test.Printf(_L("File opened for write\r\n"));
413 Test.Next(_L("Preparing to record"));
416 TLex cl(l.NextToken());
419 r = cl.Val(tmpRate,EDecimal);
420 if (r == KErrNone && (r=SamplesPerSecondToRate(tmpRate,rate))==KErrNone)
422 Test.Printf(_L("Parsed rate: %d\r\n"), tmpRate);
423 RecordFormatBuf().iRate = rate;
427 Test.Printf(_L("Parse rate failed(%d)\r\n"),r);
428 RecordFormatBuf().iRate = ESoundRate32000Hz;
431 // Get number of channels
432 TLex cl_chan(l.NextToken());
434 r = cl_chan.Val(tmpChannels,EDecimal);
437 Test.Printf(_L("Parsed %d channels\r\n"),tmpChannels);
438 RecordFormatBuf().iChannels = tmpChannels;
442 Test.Printf(_L("Parse channels failed(%d)\r\n"), r);
443 RecordFormatBuf().iChannels = 2;
446 RecordFormatBuf().iEncoding = ESoundEncoding16BitPCM;
448 // Set the record buffer configuration.
450 TTestSharedChunkBufConfig bufferConfig;
451 bufferConfig.iNumBuffers=4;
452 bufferConfig.iBufferSizeInBytes=RecordBufferSizeInBytes(RecordFormatBuf());
453 if (RecordCapsBuf().iRequestMinSize)
454 bufferConfig.iBufferSizeInBytes&=~(RecordCapsBuf().iRequestMinSize-1); // Keep the buffer length valid for the driver.
455 bufferConfig.iFlags=0;
456 PrintBufferConf(bufferConfig,Test);
457 TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
458 r=RxSoundDevice.SetBufferChunkCreate(bufferConfigBuf,chunk);
461 Test.Printf(_L("Buffer configuration not supported(%d)\r\n"),r);
465 // Set the audio record configuration.
466 RxSoundDevice.SetVolume(KSoundMaxVolume);
467 PrintConfig(RecordFormatBuf(),Test);
468 r=RxSoundDevice.SetAudioFormat(RecordFormatBuf);
471 Test.Printf(_L("Format not supported\r\n"));
475 // Get length in seconds
476 TLex cl_seconds(l.NextToken());
478 r = cl_seconds.Val(tmpSeconds,EDecimal);
481 Test.Printf(_L("Parsed %d seconds\r\n"),tmpSeconds);
485 Test.Printf(_L("Parse seconds failed(%d)\r\n"),r);
488 TInt bytesToRecord = BytesPerSecond(RecordFormatBuf())*tmpSeconds;
490 Test.Next(_L("Recording..."));
492 // Lay down a file header
494 TPtr8 headerDes((TUint8 *)&header, sizeof(struct WAVEheader), sizeof(struct WAVEheader));
497 header.ckID[0] = 'R'; header.ckID[1] = 'I';
498 header.ckID[2] = 'F'; header.ckID[3] = 'F';
500 header.wave_ckID[0] = 'W'; header.wave_ckID[1] = 'A';
501 header.wave_ckID[2] = 'V'; header.wave_ckID[3] = 'E';
503 header.fmt_ckID[0] = 'f'; header.fmt_ckID[1] = 'm';
504 header.fmt_ckID[2] = 't'; header.fmt_ckID[3] = ' ';
506 header.data_ckID[0] = 'd'; header.data_ckID[1] = 'a';
507 header.data_ckID[2] = 't'; header.data_ckID[3] = 'a';
509 header.nChannels = (TUint16)RecordFormatBuf().iChannels;
510 header.nSamplesPerSec = RateInSamplesPerSecond(RecordFormatBuf().iRate);
511 header.nBitsPerSample = 16;
512 header.nBlockAlign = TUint16((RecordFormatBuf().iChannels == 2) ? 4 : 2);
513 header.formatTag = 1; // type 1 is PCM
514 header.fmt_ckSize = 16;
515 header.nAvgBytesPerSec = BytesPerSecond(RecordFormatBuf());
516 header.data_ckSize = bytesToRecord;
517 header.ckSize = bytesToRecord + sizeof(struct WAVEheader) - 8;
519 Test.Printf(_L("Header rate:%d channels:%d tag:%d bits:%d (%d bytes/s) align %d datalen:%d fmt_ckSize:%d ckSize:%d\r\n"),
520 header.nSamplesPerSec, header.nChannels, header.formatTag, header.nBitsPerSample,
521 header.nAvgBytesPerSec, header.nBlockAlign, header.data_ckSize, header.fmt_ckSize, header.ckSize, sizeof(struct WAVEheader));
523 r = destination.Write(headerDes);
530 startTime.HomeTime();
532 // Start off by issuing a record request.
534 starttime.HomeTime();
535 TInt bytesRecorded = 0;
536 RxSoundDevice.RecordData(stat,length);
538 TInt pausesToDo = 10;
542 // Wait for the outstanding record request to complete.
545 User::WaitForAnyRequest();
546 if (stat==KRequestPending)
550 currentTime.HomeTime();
551 TInt64 elapsedTime = currentTime.Int64()-startTime.Int64(); // us
552 TTimeIntervalMicroSecondsBuf timeRecordedBuf;
553 if(RxSoundDevice.TimeRecorded(timeRecordedBuf) == KErrNone)
555 // Compare TimeRecorded with the actual elapsed time. They should be different, but not drift apart too badly...
556 TInt32 offset = TInt32(elapsedTime - timeRecordedBuf().Int64());
557 Test.Printf(_L("\telapsedTime - TimeRecorded = %d ms\n"), offset/1000);
560 // Check whether the record request was succesful.
561 TInt retOffset=stat.Int();
564 Test.Printf(_L("Record failed(%d)\r\n"),retOffset);
568 // Successfully recorded another buffer so write the recorded data to the record file and release the buffer.
569 buf.Set((const TUint8*)(chunk.Base()+retOffset),length);
570 r=destination.Write(buf);
573 Test.Printf(_L("File write failed(%d)\r\n"),r);
576 r=RxSoundDevice.ReleaseBuffer(retOffset);
579 Test.Printf(_L("Release buffer failed(%d)\r\n"),r);
583 Test.Printf(_L("Recorded %d more bytes - %d\r\n"),length,retOffset);
585 if((pausesToDo > 0) && (bytesRecorded > bytesToRecord/2))
588 Test.Printf(_L("Pause\r\n"));
589 RxSoundDevice.Pause();
590 Test.Printf(_L("Paused, sleeping for 0.5 seconds\r\n"));
591 User::After(500*1000);
592 Test.Printf(_L("Resume\r\n"));
593 RxSoundDevice.Resume();
596 // Check whether we have now recorded all the data. If more to record then queue a further request
597 bytesRecorded+=length;
598 if (bytesRecorded<bytesToRecord)
600 Test.Printf(_L("RecordData\r\n"));
601 RxSoundDevice.RecordData(stat,length);
607 RxSoundDevice.CancelRecordData(); // Stop the driver from recording.
612 TInt64 elapsedTime = endtime.Int64()-starttime.Int64(); // us
613 Test.Printf(_L("Delta time = %d\r\n"),I64LOW(elapsedTime));
614 Test.Printf(_L("Seconds in buffer: %d (%d)\r\n"), bytesRecorded / header.nAvgBytesPerSec, (bytesRecorded / header.nAvgBytesPerSec)*1000000);
616 if (I64LOW(elapsedTime) <= (bytesRecorded / header.nAvgBytesPerSec)*1000000)
618 Test.Printf(_L("Time travelling; record took less time than it should have done\r\n"));
625 Test.Printf(_L("Record finished\r\n"));
629 // Quick test block to write the output of the signal generator to a file.
630 // You'll need to comment out the reference to playdata in writetone and link
631 // the function into the command line processing (search on this function name).
633 LOCAL_C void TestWaveformGenerator()
636 Test.Next(_L("Testing waveform generator"));
637 // Parse the commandline and get a filename to use
639 TParse destinationName;
640 if (destinationName.SetNoWild(l.NextToken(),0,0)!=KErrNone)
642 Test.Printf(_L("No arg, skipping\r\n"));
646 // Open the file for writing
649 r = destination.Replace(Fs,destinationName.FullName(),EFileWrite);
652 Test.Printf(_L("Open file for write failed(%d)\r\n"), r);
655 Test.Printf(_L("File opened for write\r\n"));
656 Test.Next(_L("Preparing to record data"));
659 TLex cl(l.NextToken());
662 r = cl.Val(tmpRate,EDecimal);
663 if (r == KErrNone && (r=SamplesPerSecondToRate(tmpRate,rate))==KErrNone)
665 Test.Printf(_L("Parsed rate: %d\r\n"), tmpRate);
666 PlayFormatBuf().iRate = rate;
670 Test.Printf(_L("Parse rate failed(%d)\r\n"),r);
671 PlayFormatBuf().iRate = ESoundRate32000Hz;
674 // Get number of channels
675 TLex cl_chan(l.NextToken());
677 r = cl_chan.Val(tmpChannels,EDecimal);
680 Test.Printf(_L("Parsed %d channels\r\n"),tmpChannels);
681 PlayFormatBuf().iChannels = tmpChannels;
685 Test.Printf(_L("Parse channels failed(%d)\r\n"), r);
686 PlayFormatBuf().iChannels = 2;
689 PlayFormatBuf().iEncoding = ESoundEncoding16BitPCM;
690 PrintConfig(PlayFormatBuf(),Test);
692 TInt bufferSize=BytesPerSecond(PlayFormatBuf())/8;
693 TUint8* buffer = (TUint8*)User::Alloc(bufferSize*sizeof(TUint8));
696 Test.Printf(_L("Out of memory\r\n"));
699 TPtr8 bufferDes(buffer,bufferSize,bufferSize);
701 Test.Next(_L("Recording..."));
702 TInt i = BytesPerSecond(PlayFormatBuf())*10/bufferSize;
703 TInt bytesToRecord = i * bufferSize;
705 // Lay down a file header
707 TPtr8 headerDes((TUint8 *)&header, sizeof(struct WAVEheader), sizeof(struct WAVEheader));
710 header.ckID[0] = 'R'; header.ckID[1] = 'I';
711 header.ckID[2] = 'F'; header.ckID[3] = 'F';
713 header.wave_ckID[0] = 'W'; header.wave_ckID[1] = 'A';
714 header.wave_ckID[2] = 'V'; header.wave_ckID[3] = 'E';
716 header.fmt_ckID[0] = 'f'; header.fmt_ckID[1] = 'm';
717 header.fmt_ckID[2] = 't'; header.fmt_ckID[3] = ' ';
719 header.data_ckID[0] = 'd'; header.data_ckID[1] = 'a';
720 header.data_ckID[2] = 't'; header.data_ckID[3] = 'a';
722 header.nChannels = PlayFormatBuf().iChannels;
723 header.nSamplesPerSec = RateInSamplesPerSecond(PlayFormatBuf().iRate);
724 header.nBitsPerSample = 16;
725 header.nBlockAlign = 4;
726 header.formatTag = 1;
727 header.fmt_ckSize = 16;
728 header.nAvgBytesPerSec = BytesPerSecond(PlayFormatBuf());
729 header.data_ckSize = bytesToRecord;
730 header.ckSize = bytesToRecord + sizeof(struct WAVEheader) - 8;
732 Test.Printf(_L("Header rate:%d channels:%d tag:%d bits:%d (%d bytes/s) align %d datalen:%d fmt_ckSize:%d ckSize:%d\r\n"),
733 header.nSamplesPerSec, header.nChannels, header.formatTag, header.nBitsPerSample,
734 header.nAvgBytesPerSec, header.nBlockAlign, header.data_ckSize, header.fmt_ckSize, header.ckSize);
736 r = destination.Write(headerDes);
738 MakeSineTable(PlayFormatBuf());
739 SetToneFrequency(440,PlayFormatBuf()); // 'A'
743 WriteTone(bufferDes,PlayFormatBuf());
744 r = destination.Write(bufferDes);
747 Test.Printf(_L("Write failed(%d)\r\n"),r);
751 Test.Printf(_L("Finished\r\n"));
757 LOCAL_C void TestUnloadDrivers()
759 TInt r=User::FreeLogicalDevice(KDevSoundScName);
760 Test.Printf(_L("Unloading %S.LDD - %d\r\n"),&KDevSoundScName,r);
763 TName pddName(KDevSoundScName);
764 _LIT(KPddWildcardExtension,".*");
765 pddName.Append(KPddWildcardExtension);
766 TFindPhysicalDevice findPD(pddName);
767 TFullName findResult;
768 r=findPD.Next(findResult);
771 r=User::FreePhysicalDevice(findResult);
772 Test.Printf(_L("Unloading %S.PDD - %d\r\n"),&findResult,r);
774 findPD.Find(pddName); // Reset the find handle now that we have deleted something from the container.
775 r=findPD.Next(findResult);
787 Test.Start(_L("Load"));
788 if (Load()==KErrNotFound)
790 Test.Printf(_L("Shared chunk sound driver not supported - test skipped\r\n"));
799 Test.Next(_L("Open playback channel"));
800 r = TxSoundDevice.Open(KSoundScTxUnit0);
803 Test.Printf(_L("Open playback channel error(%d)\r\n"),r);
807 Test.Next(_L("Open record channel"));
808 r = RxSoundDevice.Open(KSoundScRxUnit0);
811 Test.Printf(_L("Open record channel error(%d)\r\n"),r);
815 Test.Next(_L("Query play formats supported"));
816 TxSoundDevice.Caps(PlayCapsBuf);
817 TSoundFormatsSupportedV02 playCaps=PlayCapsBuf();
818 PrintCaps(playCaps,Test);
820 Test.Next(_L("Query record formats supported"));
821 RxSoundDevice.Caps(RecordCapsBuf);
822 TSoundFormatsSupportedV02 recordCaps=RecordCapsBuf();
823 PrintCaps(recordCaps,Test);
825 Test.Next(_L("Connect to the file server"));
829 Test.Printf(_L("Connect to the file server error(%d)\r\n"),r);
833 if (User::CommandLineLength())
835 User::CommandLine(CommandLine);
837 TPtrC token=l.NextToken();
840 while (token.Length()!=0)
843 token.Set(l.NextToken());
845 Test.Printf(_L("Command line %d parameters\r\n"),count);
847 if (count==1) // If 1 parameter try playing a file
849 else if (count) // If there is more than 1 parameter, try recording
852 //TestWaveformGenerator();
858 Test.Next(_L("Close channels"));
859 RxSoundDevice.Close();
860 TxSoundDevice.Close();
864 // Now that both the channels are closed, unload the LDD and the PDDs.