Forum > Cocoa
[Solved] CoreAudio
Key-Real:
I have Music Engine for win and linux. No i'm using mac and wanna port this project to macOS. I have a mixer. It writes to a sound buffer. I'm looking for the best way to implement the device driver. The second test was by far the better way I could find on the net.
Key-Real:
Now I think I play only on one channel. This could explain the annoying noice. The sound is now in the correct key. This could mean the sample rate is correct now.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$linkframework AudioToolbox}{$MODE OBJFPC}uses MacOSAll,CocoaAll,crt; type TSoundState = packed record done:boolean; end; TwavHeader = packed record RIFF:array [0..3] of char; // RIFF Header Magic header ChunkSize:dword; // RIFF Chunk Size WAVE:array [0..3] of char; // WAVE Header fmt:array [0..3] of char; // FMT header Subchunk1Size:dword; // Size of the fmt chunk AudioFormat:word; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM NumOfChan:word; // Number of channels 1=Mono 2=Sterio SamplesPerSec:dword; // Sampling Frequency in Hz bytesPerSec:dword; // bytes per second blockAlign:word; // 2=16-bit mono, 4=16-bit stereo bitsPerSample:word; // Number of bits per sample Subchunk2ID:array [0..3] of char; // "data" string Subchunk2Size:dword; // Sampled data length end; var wavFile:file; wavheader:TwavHeader; procedure auCallback(inUserData:pointer; queue:AudioQueueRef; buffer:AudioQueueBufferRef); MWPascal;var SoundState : TSoundState; p:pointer; numToRead:dword; i:dword; w:word; f:single; int:integer;begin SoundState:=TSoundState(inUserData^); buffer^.mAudioDataByteSize := 1024*4; numToRead:=buffer^.mAudioDataByteSize div sizeof(single) * 2; getmem(p,numToRead); blockread(wavFile,p^,numToRead); for i:=0 to numToRead div 2 do begin w:=pword(p+i*2)^; f:=(w / $8000) - 1; psingle(buffer^.mAudioData + i*sizeof(single))^:=f; end; freemem(p); AudioQueueEnqueueBuffer(queue, buffer, 0, nil);end; procedure checkError(error:OSStatus);begin if (error <> noErr) then begin writeln('Error: ', error); halt; end;end; var auDesc:AudioStreamBasicDescription; auQueue:AudioQueueRef; auBuffers:array[0..1] of AudioQueueBufferRef; soundState:TSoundState; err:OSStatus; bufferSize:uint32;begin assign(wavFile,'unreal.wav'); reset(wavFile,1); blockread(wavFile,wavHeader,sizeof(Twavheader)); with wavHeader do begin writeln(RIFF[0],RIFF[1],RIFF[2],RIFF[3]); // RIFF Header Magic header writeln('RIFF Chunk Size ',ChunkSize); writeln(WAVE[0],WAVE[1],WAVE[2],WAVE[3]); // WAVE Header writeln(fmt[0],fmt[1],fmt[2],fmt[3]); // FMT header writeln('Size of the fmt chunk ',Subchunk1Size); writeln('Audio format ',AudioFormat); // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM writeln('Number of channels ', NumOfChan); // Number of channels 1=Mono 2=Sterio writeln('Sampling Frequency in Hz ',SamplesPerSec); // Sampling Frequency in Hz writeln('bytes per second ',bytesPerSec); // bytes per second writeln('blockAlign ',blockAlign); // 2=16-bit mono, 4=16-bit stereo writeln('Number of bits per sample ',bitsPerSample); // Number of bits per sample writeln(Subchunk2ID[0],Subchunk2ID[1],Subchunk2ID[2],Subchunk2ID[3]); // "data" string writeln('Sampled data length ',Subchunk2Size); // Sampled data length end; // stereo 16-bit interleaved linear PCM audio data at 48kHz in SNORM format auDesc.mSampleRate := wavHeader.SamplesPerSec; auDesc.mFormatID := kAudioFormatLinearPCM; auDesc.mFormatFlags := kLinearPCMFormatFlagIsFloat or kLinearPCMFormatFlagIsPacked; auDesc.mBytesPerPacket := 8; auDesc.mFramesPerPacket := 1; auDesc.mBytesPerFrame := 8; auDesc.mChannelsPerFrame := 2; auDesc.mBitsPerChannel := 32; { auDesc.mSampleRate := 48000; auDesc.mFormatID := kAudioFormatLinearPCM; auDesc.mFormatFlags := kLinearPCMFormatFlagIsBigEndian or kLinearPCMFormatFlagIsSignedInteger or kLinearPCMFormatFlagIsPacked; auDesc.mBytesPerPacket := 4; auDesc.mFramesPerPacket := 1; auDesc.mBytesPerFrame := 4; auDesc.mChannelsPerFrame := 2; auDesc.mBitsPerChannel := 16; } // our persistent state for sound playback soundState.done:=false; // most of the 0 and nullptr params here are for compressed sound formats etc. err := AudioQueueNewOutput(auDesc, @auCallback, @soundState, nil, nil, 0, auQueue); checkError(err); // generate buffers holding at most 1/16th of a second of data bufferSize := round(auDesc.mBytesPerFrame * (auDesc.mSampleRate / 16)); err := AudioQueueAllocateBuffer(auQueue, bufferSize, auBuffers[0]); checkError(err); err := AudioQueueAllocateBuffer(auQueue, bufferSize, auBuffers[1]); checkError(err); // prime the buffers auCallback(@soundState, auQueue, auBuffers[0]); auCallback(@soundState, auQueue, auBuffers[1]); // enqueue for playing AudioQueueEnqueueBuffer(auQueue, auBuffers[0], 0, nil); AudioQueueEnqueueBuffer(auQueue, auBuffers[1], 0, nil); // go! AudioQueueStart(auQueue, nil); // Our AudioQueue creation options put the CA handling on its own thread // so this is a quick hack to allow us to hear some sound. readln; // be nice even it doesn't really matter at this point AudioQueueDispose(auQueue, true);end.
how to edit this code to play on both channels?
AL:
Try this:
auDesc.mBytesPerPacket := auDesc.mChannelsPerFrame * sizeof (int32); (your bit per channel)
auDescmBytesPerFrame := auDesc.mChannelsPerFrame * sizeof (int32);
Key-Real:
If yo wanna floating point format:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var i:dword; w:int16; f:single; p:pointer; buffer:AudioBuffer; numToRead:dword; singleSize:dword; begin buffer:=outOutputData.mBuffers[0]; buffer.mDataByteSize:=1024; numToRead:=buffer.mDataByteSize div sizeof(single) * 2; getmem(p,numToRead); blockread(wavFile,p^,numToRead); for i:=0 to numToRead div 2 do begin w:=pint16(p+i*2)^; f:=(w / $8000); psingle(buffer.mData + i*sizeof(single))^:=f; end; freemem(p);
If you wanna signed integer format:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- procedure auCallback(inUserData:pointer; queue:AudioQueueRef; buffer:AudioQueueBufferRef); MWPascal;var SoundState : TSoundState; p:pointer; numToRead:dword; i:dword; w:int16; f:single; int:integer;begin SoundState:=TSoundState(inUserData^); buffer^.mAudioDataByteSize := 1024*4; numToRead := buffer^.mAudioDataByteSize; getmem(p,numToRead); blockread(wavFile,buffer^.mAudioData^,numToRead); freemem(p); AudioQueueEnqueueBuffer(queue, buffer, 0, nil); end;
--- Code: ---
auDesc.mSampleRate := wavHeader.SamplesPerSec;
auDesc.mFormatID := kAudioFormatLinearPCM;
auDesc.mFormatFlags := kLinearPCMFormatFlagIsSignedInteger or kLinearPCMFormatFlagIsPacked;
auDesc.mBytesPerPacket := 4;
auDesc.mFramesPerPacket := 1;
auDesc.mBytesPerFrame := 4;
auDesc.mChannelsPerFrame := 2;
auDesc.mBitsPerChannel := 16;
--- End code ---
Navigation
[0] Message Index
[*] Previous page