--- a/SoundStream.st Fri Jan 03 22:10:34 2020 +0100
+++ b/SoundStream.st Fri Jan 03 22:18:23 2020 +0100
@@ -15,7 +15,8 @@
FileStream subclass:#SoundStream
instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat handle1
- handle2 bufferOffset bufferSize lastErrorString fragmentSize'
+ handle2 bufferOffset bufferSize lastErrorString fragmentSize
+ openMode openAttributes'
classVariableNames:'IsInitialized UnsupportedOperationSignal ConcreteClass'
poolDictionaries:''
category:'Streams-External'
@@ -1512,7 +1513,7 @@
|buffer numSamples val scale restSamples numChannels|
(audioFormat == #F32) ifFalse:[
- self error:'must be in float mode' mayProceed:true.
+ self error:'must be in float mode' mayProceed:true.
].
numSamples := self sampleRate.
@@ -1523,24 +1524,24 @@
scale := freq * 2 * (Float pi).
numChannels == 2 ifTrue:[
- 1 to:numSamples do:[:i |
- val := (scale * i / self sampleRate) sin.
- buffer at:(i-1)*2 put:val.
- buffer at:(i-1)*2+1 put:0.
- ].
+ 1 to:numSamples do:[:i |
+ val := (scale * i / self sampleRate) sin.
+ buffer at:(i-1)*2 put:val.
+ buffer at:(i-1)*2+1 put:0.
+ ].
] ifFalse:[
- 1 to:numSamples do:[:i |
- val := (scale * i / self sampleRate) sin.
- buffer at:i put:val
- ].
+ 1 to:numSamples do:[:i |
+ val := (scale * i / self sampleRate) sin.
+ buffer at:i put:val
+ ].
].
1 to:nSeconds truncated do:[:s |
- self nextPutBytes:(numSamples*4) from:buffer startingAt:1
+ self nextPutBytes:(numSamples*4) from:buffer startingAt:1
].
restSamples := ((nSeconds - nSeconds truncated) * numSamples) truncated.
restSamples > 0 ifTrue:[
- self nextPutBytes:(restSamples*4) from:buffer startingAt:1
+ self nextPutBytes:(restSamples*4) from:buffer startingAt:1
].
"
@@ -1594,10 +1595,10 @@
|buffer numSamples val scale restSamples|
(audioFormat startsWith:#U16) ifFalse:[
- (audioFormat startsWith:#S16) ifFalse:[
- self error:'must be in 16bit mode' mayProceed:true.
- ^ self
- ]
+ (audioFormat startsWith:#S16) ifFalse:[
+ self error:'must be in 16bit mode' mayProceed:true.
+ ^ self
+ ]
].
"allocate memory for 1 sec playing time"
@@ -1608,20 +1609,20 @@
scale := freq * 2 * (Float pi).
1 to:numSamples do:[:i |
- val := (scale * i / numSamples) sin.
- val := (val * 16r7FFF) rounded.
- audioFormat == #U16 ifTrue:[
- val := val + 16r8000
- ].
- buffer at:i put:(val bitAnd:16rFFFF)
+ val := (scale * i / numSamples) sin.
+ val := (val * 16r7FFF) rounded.
+ audioFormat == #U16 ifTrue:[
+ val := val + 16r8000
+ ].
+ buffer at:i put:(val bitAnd:16rFFFF)
].
1 to:nSeconds truncated do:[:s |
- self nextPutBytes:(numSamples*2) from:buffer startingAt:1
+ self nextPutBytes:(numSamples*2) from:buffer startingAt:1
].
restSamples := ((nSeconds - nSeconds truncated) * numSamples) truncated.
restSamples > 0 ifTrue:[
- self nextPutBytes:(restSamples*2) from:buffer startingAt:1
+ self nextPutBytes:(restSamples*2) from:buffer startingAt:1
].
"of course, the frequency should be below half the
@@ -3320,6 +3321,8 @@
openWithMode:aMode attributes:attributeSpec
|ok error errorStringOrNil|
+ openMode := aMode.
+ openAttributes := attributeSpec.
%{
#ifdef SUPPORT_PORTAUDIO
static PaStreamParameters outputParameters;
@@ -3450,126 +3453,9 @@
!
reopenStream
- |ok errorStringOrNil error|
-
handle1 isNil ifTrue:[^ self].
-
-%{
-#ifdef SUPPORT_PORTAUDIO
- static PaStreamParameters outputParameters;
- PaStream *stream;
- PaError paErr;
- struct paStreamData* paStreamData;
- int nChannels, sampleRate, bytesPerSample;
-# define FRAMES_PER_BUFFER 128
- OBJ str;
-
- ok = false;
-
- str = __INST(handle1);
- paStreamData = (struct paStreamData*)__externalAddressVal(str);
- Pa_CloseStream( paStreamData->stream );
-
- /* default output device */
- outputParameters.device = Pa_GetDefaultOutputDevice();
- if (outputParameters.device == paNoDevice) {
- fprintf(stderr, "SoundStream [warning]: No default output device.\n");
- errorStringOrNil = __MKSTRING("No default output device");
- goto out;
- }
-
- if (__isSmallInteger(__INST(numberOfChannels))) {
- nChannels = __intVal(__INST(numberOfChannels));
- } else {
- nChannels = 1;
- }
- outputParameters.channelCount = nChannels;
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- // The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8
- // and aUInt8 are usually implemented by all implementations.
- // The floating point representation (paFloat32) uses +1.0 and -1.0 as the
- // maximum and minimum respectively.
- // paUInt8 is an unsigned 8 bit format where 128 is considered "ground"
-
- if (__INST(audioFormat) == @symbol(S16)) {
- outputParameters.sampleFormat = paInt16;
- bytesPerSample = 2;
- } else if (__INST(audioFormat) == @symbol(S32)) {
- outputParameters.sampleFormat = paInt32;
- bytesPerSample = 4;
- } else if (__INST(audioFormat) == @symbol(S24)) {
- outputParameters.sampleFormat = paInt24;
- bytesPerSample = 3;
- } else if (__INST(audioFormat) == @symbol(S8)) {
- outputParameters.sampleFormat = paInt8;
- bytesPerSample = 1;
- } else if (__INST(audioFormat) == @symbol(F32)) {
- outputParameters.sampleFormat = paFloat32;
- bytesPerSample = 4;
- } else if (__INST(audioFormat) == @symbol(U8)) {
- outputParameters.sampleFormat = paUInt8;
- bytesPerSample = 1;
- } else {
- fprintf(stderr, "SoundStream [warning]: unknown format - using U8\n");
- outputParameters.sampleFormat = paUInt8;
- bytesPerSample = 1;
- }
-
- if (__isSmallInteger(__INST(sampleRate))) {
- sampleRate = __intVal(__INST(sampleRate));
- } else {
- fprintf(stderr, "SoundStream [warning]: using default sampleRate 8000\n");
- sampleRate = 8000;
- }
-
- paStreamData = (struct paStreamData*)malloc(sizeof(struct paStreamData));
- if (paStreamData == NULL) {
- fprintf(stderr, "SoundStream [warning]: failed to allocate paStream\n");
- errorStringOrNil = __MKSTRING("failed to allocate paStream");
- goto out;
- }
-
- paErr = Pa_OpenStream(
- &stream,
- NULL, /* no input */
- &outputParameters,
- sampleRate,
- FRAMES_PER_BUFFER,
- paClipOff, /* we won't output out of range samples so don't bother clipping them */
- paCallback,
- paStreamData );
-
- if (paErr != paNoError) {
- fprintf(stderr, "SoundStream [warning]: openStream: %s\n", Pa_GetErrorText( paErr ));
- free(paStreamData);
- errorStringOrNil = __MKSTRING(Pa_GetErrorText( paErr ));
- goto out;
- }
- paStreamData->stream = stream;
-
- paStreamData->readOffset = 0;
- paStreamData->bytesPerSample = bytesPerSample;
- paStreamData->nChannels = nChannels;
-
- paStreamData->currentBuffer = NULL;
- paStreamData->lastBuffer = NULL;
- paStreamData->freeList = NULL;
- paStreamData->hasFinished = 0;
-
- ok = true;
-out:;
-#endif /* SUPPORT_PORTAUDIO */
-
-%}.
- ok == false ifTrue:[
- lastErrorString := errorStringOrNil.
- lastErrorNumber := error ? -1.
- self openError:error.
- "normally not reached"
- ^ nil.
- ].
+ self closeFile.
+ self openWithMode:openMode attributes:openAttributes
! !
!SoundStream::PortAudio methodsFor:'private'!
@@ -3611,25 +3497,25 @@
supportedAudioFormats
"return a collection of supported audio formats.
possibly returned symbols are:
- U8 unsigned 8bit samples
- S8 signed 8bit samples
- U16 unsigned 16bit samples in native format
- U16_LE unsigned 16bit big endian samples
- U16_BE unsigned 16bit big endian samples
- S16 signed 16bit little endian samples in native format
- S16_LE signed 16bit little endian samples
- S16_BE signed 16bit big endian samples
- S24 signed 24bit little endian samples in native format
- S24_LE signed 24bit little endian samples
- S24_BE signed 24bit big endian samples
- S32 signed 32bit little endian samples in native format
- S32_LE signed 32bit little endian samples
- S32_BE signed 32bit big endian samples
- F32 float samples
- MPEG audio mpeg encoded
- MU_LAW u-law encoded 8bit samples
- A_LAW a-law encoded 8bit samples
- IMA_ADPCM adpcm encoded
+ U8 unsigned 8bit samples
+ S8 signed 8bit samples
+ U16 unsigned 16bit samples in native format
+ U16_LE unsigned 16bit big endian samples
+ U16_BE unsigned 16bit big endian samples
+ S16 signed 16bit little endian samples in native format
+ S16_LE signed 16bit little endian samples
+ S16_BE signed 16bit big endian samples
+ S24 signed 24bit little endian samples in native format
+ S24_LE signed 24bit little endian samples
+ S24_BE signed 24bit big endian samples
+ S32 signed 32bit little endian samples in native format
+ S32_LE signed 32bit little endian samples
+ S32_BE signed 32bit big endian samples
+ F32 float samples
+ MPEG audio mpeg encoded
+ MU_LAW u-law encoded 8bit samples
+ A_LAW a-law encoded 8bit samples
+ IMA_ADPCM adpcm encoded
the set of returned symbols depends on the underlying sound hardware.
"