OPErr XCloseMPEGEncodeStream(XMPEGEncodeData *stream, XPTR *pReturnedBuffer, unsigned long *pReturnedSize)
{
	MPEGEncoderPrivate	*pPrivate;
	OPErr				err;

	err = NO_ERR;
	if (stream)
	{
		pPrivate = MPEG_ENCODE_PRIVATE(stream);
		if (pPrivate->encoder)
		{
			MPG_EncodeFreeStream(pPrivate->encoder);
		}
		if (pReturnedSize && pReturnedBuffer)
		{
			*pReturnedBuffer = pPrivate->pCompressedAudio;
			*pReturnedSize = pPrivate->compressedAudioPosition;
		}
		XDisposePtr((XPTR)stream->pPrivateData);
		XDisposePtr((XPTR)stream);
	}
	else
	{
		BAE_ASSERT(FALSE);
		err = PARAM_ERR;
	}
	return err;
}
示例#2
0
void * mod_realloc(void* ptr, long size)
{
    XPTR	p;

    p = NULL;
    if (ptr)
    {
        p = XNewPtr(size);
        if (p)
        {
            size = XGetPtrSize((XPTR)ptr);	// get old size
            if (size)
            {
                XBlockMove(ptr, p, size);
            }
            else
            {
                XDisposePtr(p);
                p = NULL;	// can't get size, so fail
            }
            XDisposePtr(ptr);
        }
    }
    return p;
}
示例#3
0
// Free cache entry
static void PV_FreeCacheEntry(CacheSampleInfo *pCache)
{
    if (pCache)
	{
	    if (pCache->pSampleData)
		{
		    XDisposePtr(pCache->pMasterPtr);
		}
	    XDisposePtr(pCache);
	}
}
示例#4
0
// Given a song pointer, this will attempt to free all memory related to the song: midi
// data, instruments, samples, etc. It can fail and will return STILL_PLAYING if
// midi data is still being accessed, or samples, or instruments.
//
// If you pass NULL, then this function will be called recursively will all songs
// currently playing.
OPErr GM_FreeSong(void *threadContext, GM_Song *pSong)
{
    OPErr	err;
    XPTR	midiData;

    err = NO_ERR;
    GM_EndSong(threadContext, pSong);
    if (pSong)
	{
	    GM_KillSongNotes(pSong);		// we must kill the notes because we are about to free
	    // instrument memory
	    if (pSong->processingSlice == FALSE)
		{
		    GM_PauseSong(pSong);
		    midiData = (XPTR)pSong->midiData;		// save midi pointer now
		    pSong->midiData = NULL;					// and disable midi decoder now, just
		    // in case the decoder thread comes to life
		    GM_SetCacheSamples(pSong, FALSE);
		    err = GM_UnloadSongInstruments(pSong);
		    if (err == NO_ERR)
			{
			    if (pSong->disposeSongDataWhenDone)
				{
				    XDisposePtr(midiData);
				}
			    XDisposePtr((XPTR)pSong->controllerCallback);

#if 0 && USE_CREATION_API == TRUE
			    if (pSong->pPatchInfo)
				{
				    PV_FreePatchInfo(pSong);	// must free before killing pSong pointer
				}
#endif

			    XDisposePtr((XPTR)pSong);
			}
		    else
			{
				//DebugStr("\pGM_FreeSong::GM_UnloadSongInstruments::STILL_PLAYING");
			}
		}
	    else
		{
		    //DebugStr("\pGM_FreeSong::STILL_PLAYING");
		    err = STILL_PLAYING;
		}
	}
    return err;
}
示例#5
0
XBOOL XIsSampleUsedInAllInstruments(XShortResourceID soundSampleID, XShortResourceID *pWhichInstrument)
{
    InstrumentResource	*theX;
    short int			count, totalInstruments;
    XBOOL				used;
    long				size;
    XShortResourceID	instArray[MAX_INSTRUMENTS * MAX_BANKS];

    used = FALSE;
    totalInstruments = XGetInstrumentArray(instArray, MAX_INSTRUMENTS * MAX_BANKS);
    if (totalInstruments && pWhichInstrument)
	{
	    for (count = 0; count < totalInstruments; count++)
		{
		    theX = (InstrumentResource *)XGetAndDetachResource(ID_INST, instArray[count], &size);
		    if (theX)
			{
			    used = XIsSoundUsedInInstrument(theX, soundSampleID);
			    XDisposePtr((XPTR)theX);
			    if (used)
				{
				    *pWhichInstrument = instArray[count];
				    break;
				}
			}
		}
	}
    return used;
}
JNIEXPORT jlong JNICALL
    Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResourceFromByteArray(JNIEnv* e, jobject thisObj, jbyteArray bankData, jint length) 
{
    XFILE file = NULL;
    void	*pData = NULL;

    TRACE0("Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResourceFromByteArray.\n");

    pData = XNewPtr(length); // can have memory error

    if (!pData)
	{
	    ERROR0("Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResourceFromByteArray failed to allocate memory for soundbank\n");
	    return 0;
	}

    (*e)->GetByteArrayRegion(e, bankData, (jint)0, (jint)length, (jbyte*)pData);

    file = XFileOpenResourceFromMemory(pData, length, TRUE);

    if (!file)
	{
	    ERROR0("Failed to create resource file from data \n");
	    XDisposePtr(pData);
	    return 0;
	}

    TRACE1("Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResourceFromByteArray completed, returning %lu.\n", file);

    return (jlong) (INT_PTR) file;
}
示例#7
0
/*
** Return the number of INST's and an array of resource IDs
*/
short int XGetInstrumentArray(XShortResourceID *instArray, short maxArraySize)
{
    short int	icount, totalCount;
    long		size;
    XPTR		theRes;

    /* Collect INST resources
     */
    totalCount = 0;
    if (instArray)
	{
	    for (icount = 0; icount < maxArraySize; icount++)
		{
		    theRes = XGetAndDetachResource(ID_INST, icount, &size);
		    if (theRes)
			{
			    XDisposePtr(theRes);
			    instArray[totalCount++] = (XShortResourceID)icount;
			    if (totalCount > maxArraySize)
				{
				    totalCount = maxArraySize;
				    break;
				}
			}
		}
	    XBubbleSortArray((short *)instArray, (short)totalCount);
	}
    return totalCount;
}
示例#8
0
static void PV_FreeCaptureAudioStream(GM_CaptureAudioStream *found)
{
    GM_CaptureAudioStream *next, *last;

    found = PV_CaptureAudioStreamGetFromReference(found);		// verify as valid
    if (found)
	{
	    if (found->streamID == CAPTURE_STREAM_ID)
		{
		    last = next = theCaptureStreams;
		    while (next)
			{
			    if (next == found)								// found object in list?
				{
				    if (next == theCaptureStreams)				// is object the top object
					{
					    theCaptureStreams = next->pNext;		// yes, change to next object
					}
				    else
					{
					    if (last)						// no, change last to point beyond next
						{
						    last->pNext = next->pNext;
						}
					}
				    next->streamID = 0;
				    XDisposePtr(next);					// clean up
				    break;
				}
			    last = next;
			    next = next->pNext;
			}
		}
	}
}
// XProcessMPEGEncoder() seems to prepend some number zero samples to the waveform.
// Scan the first frame buffer for the first nonzero sample and
// set *startFrame to the offset to it.
static unsigned long PV_ScanForAudioDataFromMPEG(XPTR pMPEGStream,
													unsigned long mpegStreamSize,
													unsigned long *pFrameBufferCount,
													OPErr *pErr)
{
unsigned long		firstNonSilentFrame;
XMPEGDecodedData	*stream;
OPErr				err;
char				*tempBuffer;
XBOOL				done;

	if (pErr)
	{
		*pErr = NO_ERR;
	}
	firstNonSilentFrame = 0;
	stream = XOpenMPEGStreamFromMemory(pMPEGStream, mpegStreamSize, &err);
	if (stream)
	{
		if (pFrameBufferCount)
		{
			if (stream->maxFrameBuffers > *pFrameBufferCount)
			{
				*pFrameBufferCount = stream->maxFrameBuffers;
			}
		}
		
		tempBuffer = (char *)XNewPtr(stream->frameBufferSize * sizeof(long));
		if (tempBuffer)
		{
			err = XFillMPEGStreamBuffer(stream, tempBuffer, &done);
			if (err == NO_ERR)
			{
				firstNonSilentFrame = PV_ScanForAudioData((short int*)tempBuffer, 
												stream->frameBufferSize, 
												(unsigned long)stream->channels);
			}
			XDisposePtr(tempBuffer);
		}

		XCloseMPEGStream(stream);
	}
	if (pErr)
	{
		*pErr = err;
	}
#if 0
	if (firstNonSilentFrame < 448)	//481
	{
		return 448;
	}
#endif
	return firstNonSilentFrame;
}
示例#10
0
XShortResourceID XCheckValidInstrument(XShortResourceID theID)
{
    InstrumentResource	*theX;
    short int			totalSnds;
    XShortResourceID	sndArray[MAX_SAMPLES];
    short int			count;
    XShortResourceID	badLoad;
    XPTR				theSnd;
    long				size;

    badLoad = 0;
    theX = (InstrumentResource *)XGetAndDetachResource(ID_INST, theID, &size);
    if (theX)
	{
	    totalSnds = XCollectSoundsFromInstrument(theX, sndArray, MAX_SAMPLES);
	    XDisposePtr((XPTR)theX);
	    for (count = 0; count < totalSnds; count++)
		{
		    theSnd = XGetAndDetachResource(ID_CSND, sndArray[count], &size);		// look for compressed version first
		    if (theSnd == NULL)
			{
			    theSnd = XGetAndDetachResource(ID_SND, sndArray[count], &size);
			}
		    if (theSnd == NULL)
			{
			    theSnd = XGetAndDetachResource(ID_ESND, sndArray[count], &size);
			}
		    if (theSnd == NULL)
			{
			    badLoad = sndArray[count];
			}
		    XDisposePtr(theSnd);
		    if (badLoad)
			{
			    break;
			}
		}
	}
    return badLoad;
}
示例#11
0
short int XCollectSoundsFromInstrumentID(XShortResourceID theID, XShortResourceID *sndArray, short maxArraySize)
{
    InstrumentResource	*theX;
    short int			totalSnds;
    long				size;

    totalSnds = 0;
    theX = (InstrumentResource *)XGetAndDetachResource(ID_INST, theID, &size);
    if (theX)
	{
	    totalSnds = XCollectSoundsFromInstrument(theX, sndArray, maxArraySize);
	    XDisposePtr((XPTR)theX);
	}
    return totalSnds;
}
示例#12
0
// allocate and return an list of ID's collected from ID_SND, ID_CSND, ID_ESND. pCount will
// be the number of ID's, and the long array will be the list. use XDisposePtr on the return
// pointer
XLongResourceID * XGetAllSoundID(long *pCount)
{
    long			count, size, totalResourceCount, resourceIndex, sampleCount;
    XResourceType	resType;
    XLongResourceID	theID;
    char			name[256];
    XPTR			data;
    XLongResourceID	*pArray;

    pArray = NULL;
    sampleCount = 0;
    totalResourceCount = XCountTypes(NULL);		// get total number of resource types
    if (totalResourceCount && pCount)
	{
	    pArray = (XLongResourceID *)XNewPtr((long)sizeof(XLongResourceID) * MAX_SAMPLES);
	    if (pArray)
		{
		    for (resourceIndex = 0; resourceIndex < totalResourceCount; resourceIndex++)
			{
			    resType = XGetIndexedType(NULL, resourceIndex);
			    if ( (resType == ID_SND) || (resType == ID_CSND) || (resType == ID_ESND) )
				{
				    for (count = 0; ; count++)
					{
					    data = XGetIndexedResource(resType, &theID, count, name, &size);
					    if (data)
						{
						    XDisposePtr(data);			// free pointer resource
						    pArray[sampleCount++] = theID;
						    if (sampleCount == (MAX_SAMPLES-1))
							{
							    break;
							}
						}
					    else
						{
						    break;
						}
					}
				}
			}
		    *pCount = sampleCount;
		}
	}
    return pArray;
}
示例#13
0
XMPEGDecodedData * XOpenMPEGStreamFromMemory(XPTR pBlock, unsigned long blockSize, OPErr *pErr)
{
	XMPEGDecodedData	*pStream;

	if (!pBlock || !blockSize || !pErr)
	{
		BAE_ASSERT(FALSE);
		return NULL;
	}
	
#if WRITE_FILE
	PV_SetupWriteFile();
#endif
	pStream = (XMPEGDecodedData *)XNewPtr(sizeof(XMPEGDecodedData));
	if (pStream)
	{
		pStream->stream = MPG_NewStreamFromMemory(pBlock, blockSize);
		if (pStream->stream)
		{
			pStream->sampleRate = UNSIGNED_LONG_TO_XFIXED(MPG_GetSampleRate(pStream->stream));
			pStream->bitSize = (XBYTE)MPG_GetBitSize(pStream->stream);
			pStream->channels = (XBYTE)MPG_GetChannels(pStream->stream);
			pStream->bitrate = MPG_GetBitrate(pStream->stream);

			pStream->lengthInBytes = MPG_GetSizeInBytes(pStream->stream);
			pStream->lengthInSamples = MPG_GetNumberOfSamples(pStream->stream);

			pStream->frameBufferSize = (unsigned long)MPG_GetBufferSize(pStream->stream);
			pStream->maxFrameBuffers = (unsigned long)MPG_GetMaxBuffers(pStream->stream);
			*pErr = NO_ERR;
		}
		else
		{
			BAE_ASSERT(FALSE);
			XDisposePtr((XPTR)pStream);
			pStream = NULL;
			*pErr = BAD_FILE;
		}
	}
	else
	{
		BAE_ASSERT(FALSE);
		*pErr = MEMORY_ERR;
	}
	return pStream;
}
示例#14
0
// Given an array of instruments, this will return an array of SND resources that are required to load
// these instruments
short int XGetTotalKeysplits(XShortResourceID *instArray, short int totalInstruments, 
			     XShortResourceID *sndArray, short int totalSnds)
{
    register short int	count, count2, count3, count4, keyCount;
    KeySplit			theSplit;
    InstrumentResource	*theInstrument;
    char				*pLoaded;
    long				size;

    keyCount = 0;
    if (instArray && totalInstruments && sndArray && totalSnds)
	{
	    pLoaded = (char *)XNewPtr((long)sizeof(char) * totalSnds);
	    if (pLoaded)
		{
		    for (count = 0; count < totalInstruments; count++)
			{
			    theInstrument = (InstrumentResource *)XGetAndDetachResource(ID_INST, instArray[count], &size);
			    if (theInstrument)
				{
				    count3 = (short)XGetShort(&theInstrument->keySplitCount);
				    for (count2 = 0; count2 < count3; count2++)
					{
					    XGetKeySplitFromPtr(theInstrument, count2, &theSplit);
					    count4 = PV_ConvertResourceID2Index(sndArray, totalSnds, theSplit.sndResourceID);
					    if (count4)
						{
						    if (pLoaded[count4] == 0)
							{
							    pLoaded[count4] = 1;
							    keyCount++;
							}
						}
					}
				}
			}
		    XDisposePtr((XPTR)pLoaded);
		}
	}
    return keyCount;
}
示例#15
0
OPErr XCloseMPEGStream(XMPEGDecodedData *pStream)
{
	OPErr	err;

#if WRITE_FILE
	PV_CleanupWriteFile();
#endif
	err = NO_ERR;
	if (pStream)
	{
		if (pStream->stream)
		{
			MPG_FreeStream(pStream->stream);
		}
		XDisposePtr((XPTR)pStream);
	}
	else
	{
		BAE_ASSERT(FALSE);
		err = PARAM_ERR;
	}
	return err;
}
示例#16
0
XERR XCopyInstrumentResources(XShortResourceID *pInstCopy, short int instCount, 
			      XFILE readFileRef, XFILE writeFileRef, XBOOL copyNames)
{
    short int		count;
    XPTR			pData;
    short int		theID;
    long			size;
    char			theName[256];

    if (instCount && pInstCopy)
	{
	    XFileUseThisResourceFile(readFileRef);		/* from resource file */
	    for (count = 0; count < instCount; count++)
		{
		    theID = pInstCopy[count];
		    XFileUseThisResourceFile(writeFileRef);
		    pData = XGetFileResource(writeFileRef, ID_INST, theID, theName, &size);
		    if (pData == NULL)		// check to see that its not there already!!
			{
			    XFileUseThisResourceFile(readFileRef);		/* from resource file */
			    pData = XGetFileResource(readFileRef, ID_INST, theID, theName, &size);
			    if (pData)
				{
				    XFileUseThisResourceFile(writeFileRef);
				    if (copyNames == FALSE)
					{
					    theName[0] = 0;
					}
				    XAddResource(ID_INST, theID, theName, pData, size);
				}
			}
		    XDisposePtr(pData);
		}
	}
    return 0;
}
示例#17
0
static OPErr MixerSourceLineCallbackProc(void* context, GM_StreamMessage message, GM_StreamData* pAS)
{
    JNIEnv* e = (JNIEnv*)context;														    
    VTRACE2("MixerSourceLineCallbackProc, context: %lx, message: %d\n", context, message);

    // for STREAM_CREATE, we just need to allocate the buffer.
    // we need to convert from gmData->dataLength (number of frames) to number of bytes.
    // $$kk: 03.15.98: this is the same calculation done by PV_GetSampleSizeInBytes.  however, this
    // method is not available outside GenAudioStreams.c right now.

    if (message == STREAM_CREATE)
	{
	    jint    const byteCount = pAS->dataLength * pAS->channelSize * (pAS->dataBitSize / 8);

	    VTRACE1("STREAM_CREATE: %lx\n", pAS->userReference);
	    VTRACE3("STREAM_CREATE: byteCount = %d, dataLength = %lu, frameSize = %d.\n", byteCount, pAS->dataLength, (pAS->channelSize * (pAS->dataBitSize / 8)) );

	    pAS->pData = XNewPtr(byteCount);
	    if (!pAS->pData)
		{
		    ERROR1("MixerSourceLineCallbackProc: STREAM_CREATE: Failed to allocate %d bytes\n", byteCount);
		    return MEMORY_ERR;
		}

	    VTRACE1("STREAM_CREATE: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_DESTROY)
	{
	    VTRACE1("STREAM_DESTROY: %lx\n", pAS->userReference);

	    CallToJavaStreamDestroy(e, (jobject)pAS->userReference);

	    // $$kk: 12.21.98: for some reason, this causes the vm to crash some
	    // random time later.  so we have a memory leak here.  i don't know
	    // why we can't release the memory here....
		
	    // $$kk: 03.22.00: i am putting this code back in.  the memory leak is
	    // causing problems, and so far i have not been able to reproduce the
	    // crash.  the memory leak is reported in bug #4319431: "Memory leaks
	    // on opening and closing source DataLines."

	    if (pAS->pData)
		{
		    XDisposePtr(pAS->pData);
		}

	    VTRACE1("STREAM_DESTROY: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_GET_DATA)
	{		
	    int length;
	    int frameLengthInBytes = pAS->channelSize * (pAS->dataBitSize / 8);
	    jbyteArray array = (jbyteArray)(*e)->GetObjectField(e, (jobject)pAS->userReference, g_dataArrayFieldID);

	    if (array == NULL) 
		{
		    ERROR0("STREAM_GET_DATA: failed to get array\n");
		    return GENERAL_BAD;
		}

	    // make the callback.
	    // pAS->dataLength is the length in FRAMES.
	    // length returned is length in FRAMES.
	    length = (int)CallToJavaStreamGetData(e, (jobject)pAS->userReference, array, (jint)pAS->dataLength);

	    // length will be -1 when the stream finishes
		
	    if (length < 0)
		{
		    VTRACE0("STREAM_GET_DATA: got negative length; stopping stream\n");
		    return STREAM_STOP_PLAY;
		}
													   
	    // get the relevant array elements

	    // $$kk: 03.15.98: can we avoid this copy??
	    (*e)->GetByteArrayRegion(e, array, (jint)0, (jint)(length * frameLengthInBytes), (jbyte*)(pAS->pData));
		
	    // $$kk: 04.21.00: fix for bug #4332327: "JNI leaks local references on 
	    // keeping a SourceLine open for long."
	    (*e)->DeleteLocalRef(e, array);		
		
	    // set dataLength to the number of frames read
	    pAS->dataLength = length;

	    VTRACE2("STREAM_GET_DATA: length: %d, pAS->dataLength: %lu\n", length, pAS->dataLength);
	    VTRACE1("STREAM_GET_DATA: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_START)
	{
	    TRACE2("STREAM_START: stream: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamStart(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_START: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_STOP)
	{
	    TRACE2("STREAM_STOP: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamStop(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_STOP: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_EOM)
	{
	    TRACE2("STREAM_EOM: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamEOM(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_EOM: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_ACTIVE)
	{
	    TRACE2("STREAM_ACTIVE: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamActive(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_ACTIVE: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_INACTIVE)
	{
	    TRACE2("STREAM_INACTIVE: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamInactive(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_INACTIVE: %lx completed\n", pAS->userReference);
	}

    else
	{
	    ERROR1("Bad message code in MixerSourceLineCallbackProc() : %d\n", message);
	    return GENERAL_BAD;
	}

    return NO_ERR;
}
示例#18
0
// Multi source user config based streaming
// This will setup a streaming audio object.
//
// INPUT:
//	userReference	This is a reference value that will be returned and should be passed along to all AudioStream
//					functions.
//
//	pProc			is a GM_StreamObjectProc proc pointer. At startup of the streaming the proc will be called
//					with STREAM_CREATE, then followed by two STREAM_GET_DATA calls to get two buffers of data,
//					and finally STREAM_DESTROY when finished.
//
// OUTPUT:
//	long			This is an audio stream reference number. Will be 0 if error
void		*GM_AudioCaptureStreamSetup(	void *platformContext,		// platform context
						void *userReference, 			// user reference
						GM_StreamObjectProc pProc, 		// control callback
						UINT32 bufferSize, 		// buffer size in bytes
						XFIXED sampleRate,				// Fixed 16.16
						char dataBitSize,				// 8 or 16 bit data
						char channelSize,				// 1 or 2 channels of date
						OPErr *pErr)
{
    GM_CaptureAudioStream	*pStream;
    void *					returnedReference;
    OPErr					haeErr;

    haeErr = NO_ERR;
    returnedReference = 0;
    if ( (pErr) && (pProc) && ( (channelSize >= 1) || (channelSize <= 2) ) && ( (dataBitSize == 8) || (dataBitSize == 16) ) )
	{
	    returnedReference = PV_GetEmptyCaptureAudioStream();
	    if (returnedReference)
		{
		    pStream = (GM_CaptureAudioStream *)returnedReference;

		    pStream->streamCallback = pProc;
		    pStream->streamUnderflow = FALSE;
		    pStream->reference = userReference;
		    pStream->samplesCaptured = 0; 
		    pStream->streamShuttingDown = FALSE;

		    pStream->streamData.pData = NULL;
		    pStream->streamData.userReference = pStream->reference;
		    pStream->streamData.streamReference = pStream;
		    pStream->streamData.sampleRate = sampleRate;
		    pStream->streamData.dataBitSize = dataBitSize;
		    pStream->streamData.channelSize = channelSize;
		    pStream->platformContext = platformContext;

		    // $$kk: 10.13.98: right now we are not allowing the user to set the size; 
		    // we force use of the device value....
		    pStream->streamData.dataLength = bufferSize / PV_GetSampleSizeInBytes(&pStream->streamData);

		    // $$kk: 10.09.98: here we request allocation of enough memory for both buffers
		    haeErr = (*pProc)(platformContext, STREAM_CREATE, &pStream->streamData);
		    if (haeErr == NO_ERR)
			{
			    pStream->pStreamBuffer1 = pStream->streamData.pData;
				// convert from frames to bytes
				// $$kk: 10.09.98: we divide the allocated data into two buffers, each half the total length
			    pStream->streamBufferLength = pStream->streamData.dataLength * PV_GetSampleSizeInBytes(&pStream->streamData) / 2;
			    pStream->pStreamBuffer2 = (char *)pStream->streamData.pData + pStream->streamBufferLength;

			    PV_AddCaptureAudioStream(pStream);		// ok add stream
			}
		    else
			{
			    pStream->streamCallback = NULL;
			    (*pProc)(platformContext, STREAM_DESTROY, &pStream->streamData);
			    haeErr = DEVICE_UNAVAILABLE;
			}
		}
	    else
		{
		    haeErr = MEMORY_ERR;
		}
	}
    else
	{
	    haeErr = PARAM_ERR;
	}
    if (haeErr)
	{
	    XDisposePtr((XPTR)returnedReference);
	    returnedReference = 0;
	}
    if (pErr)
	{
	    *pErr = haeErr;
	}
    return returnedReference;
}
示例#19
0
/*
**	This will walk through all Instrument resources and collect all snd resources
**	that are used.
*/
short int XGatherAllSoundsFromAllInstruments(XShortResourceID *pSndArray, short int maxArraySize)
{
    short int			count, icount, sndCount, jcount;
    XShortResourceID	soundID;
    XBOOL				goodSound;
    XShortResourceID	instArray[MAX_INSTRUMENTS * MAX_BANKS];
    short int			totalInstruments;
    XShortResourceID	sndArray[MAX_SAMPLES];
    short int			totalSnds;
    XShortResourceID	*completeSndArray;
    short int			completeSndCount;
    InstrumentResource	*theX;
    long				size;

    completeSndCount = 0;
    sndCount = 0;
    completeSndArray = (XShortResourceID *)XNewPtr(MAX_INSTRUMENTS * MAX_BANKS * 128L * sizeof(XShortResourceID));
    if (completeSndArray)
	{
	    sndCount = 0;
	    totalInstruments = XGetInstrumentArray(instArray, MAX_INSTRUMENTS * MAX_BANKS);
	    if (totalInstruments)
		{
		    for (count = 0; count < totalInstruments; count++)
			{
			    theX = (InstrumentResource *)XGetAndDetachResource(ID_INST, instArray[count], &size);
			    if (theX)
				{
				    totalSnds = XCollectSoundsFromInstrument(theX, sndArray, MAX_SAMPLES);
				    XDisposePtr((XPTR)theX);

				    for (icount = 0; icount < totalSnds; icount++)
					{
					    completeSndArray[completeSndCount++] = sndArray[icount];
					}
				}
			}
		    XBubbleSortArray((short *)completeSndArray, (short)completeSndCount);

		    // Remove duplicates
		    for (jcount = 0; jcount < completeSndCount; jcount++)
			{
			    goodSound = TRUE;
			    soundID = completeSndArray[jcount];
			    for (count = 0; count < sndCount; count++)
				{
				    if (soundID == pSndArray[count])
					{
					    goodSound = FALSE;
					    break;
					}
				}
			    if (goodSound)
				{
				    if (sndCount < maxArraySize)
					{
					    pSndArray[sndCount++] = soundID;
					}
				}
			}
		}
	    XDisposePtr((XPTR)completeSndArray);
	}
    return sndCount;
}
示例#20
0
OPErr GM_GetSongInstrumentChanges(void *theSongResource, GM_Song **outSong, XBYTE **outTrackNames)
{
    OPErr		err;
    ScanMode 	saveScan;
    XBOOL		saveLoop,saveAlive;
    GM_Song		*theSong;
    void		*newMidiData;
	
    err = NO_ERR;
    // don't need a thread context here because we don't callback
    theSong = GM_LoadSong(NULL, NULL, 0, theSongResource, NULL, 0L, NULL, FALSE, TRUE, &err);
    if (!theSong)
	{
	    return err;
	}	
    err = PV_ConfigureMusic(theSong);
    // first pass: count the program changes, so we know how big to make our
    if (err == NO_ERR)
	{
	    theSong->pPatchInfo = (PatchInfo *)XNewPtr((INT32)sizeof(PatchInfo));
	    if (theSong->pPatchInfo)
		{
		    saveScan = theSong->AnalyzeMode;
		    theSong->AnalyzeMode = SCAN_COUNT_PATCHES;
		    saveLoop = theSong->loopSong;
		    theSong->loopSong = FALSE;
		    saveAlive = theSong->SomeTrackIsAlive;
		    theSong->SomeTrackIsAlive = TRUE;
		    while (theSong->SomeTrackIsAlive)
			{
			    // don't need a thread context here because we don't callback
			    err = PV_ProcessMidiSequencerSlice(NULL, theSong);
			    if (err)
				{
				    break;
				}
			}
		}
	    else
		{
		    err = MEMORY_ERR;
		}
	}
    // now theSong->pPatchInfo->pgmCount points to the number of program
    // changes without immediately preceding bank changes, and rsCount
    // is the number of program changes that were discovered to have been
    // written into the file in running status mode (implement this later)
    // done in two passes because we can't keep changing the midi data
    // pointer, so we have figure out how big it needs to be first and
    // move it in place

    if (err == NO_ERR)
	{
	    // expand the ptr enough to accomodate bank messages (4 bytes each)
	    newMidiData = XNewPtr(XGetPtrSize(theSong->midiData) + theSong->pPatchInfo->instrCount * 4);
	    XBlockMove(theSong->midiData,newMidiData,XGetPtrSize(theSong->midiData));
	    XDisposePtr(theSong->midiData);
	    theSong->midiData = newMidiData;

	    // start over
	    err = PV_ConfigureMusic(theSong);

	    // second pass: get the program changes, add bank events before each one
	    if (err == NO_ERR)
		{
		    GM_SetSongMetaEventCallback(theSong, PV_TrackNameCallback, (INT32)outTrackNames);
		    saveScan = theSong->AnalyzeMode;
		    theSong->AnalyzeMode = SCAN_FIND_PATCHES;
		    saveLoop = theSong->loopSong;
		    theSong->loopSong = FALSE;
		    saveAlive = theSong->SomeTrackIsAlive;
		    theSong->SomeTrackIsAlive = TRUE;
		    while (theSong->SomeTrackIsAlive)
			{
				// don't need a thread context here because we don't callback
			    err = PV_ProcessMidiSequencerSlice(NULL, theSong);
			    if (err)
				{
				    break;
				}
			}
		}
	}
    // since there was an error, caller won't be using the song
    if (err)
	{
	    if (theSong->pPatchInfo)
		{
		    XDisposePtr(theSong->pPatchInfo);
		}
	    // don't need a thread context here because we don't callback
	    GM_FreeSong(NULL, theSong);	// we ignore the error codes, because it should be ok to dispose
	    // since this song was never engaged
	}
    else
	{
	    *outSong = theSong;
	}
    return err;
}
示例#21
0
// Given a list of instruments, this will return the sample ID's that are required to load
// all of these instruments
short int XGetSamplesFromInstruments(XShortResourceID *pInstArray, short int maxInstArraySize, 
				     XShortResourceID *pSndArray, short int maxSndArraySize)
{
    register long		count, instCount, sndCount, newCount, completeSndCount;
    XShortResourceID	soundID;
    XShortResourceID	*completeSndArray;
    XBOOL				goodSound;
    InstrumentResource	*theX;
    long				size;

    sndCount = 0;
    completeSndArray = (XShortResourceID *)XNewPtr(sizeof(XShortResourceID) * MAX_INSTRUMENTS * 128L);
    if (completeSndArray)
	{
	    if ( (pInstArray) && (pSndArray) )
		{
		    instCount = 0;
		    for (count = 0; count < maxInstArraySize; count++)
			{
			    if (pInstArray[count] != (XShortResourceID)-1)
				{
				    instCount++;
				}
			    else
				{
				    break;
				}
			}
		    for (count = 0; count < maxSndArraySize; count++)
			{
			    pSndArray[count] = (XShortResourceID)-1;
			    completeSndArray[count] = (XShortResourceID)-1;
			}


		    completeSndCount = 0;
		    for (count = 0; count < instCount; count++)
			{
			    theX = (InstrumentResource *)XGetAndDetachResource(ID_INST, pInstArray[count], &size);
			    if (theX)
				{
				    newCount = XCollectSoundsFromInstrument(theX, &completeSndArray[completeSndCount], 128);
				    XDisposePtr((XPTR)theX);
				    completeSndCount += newCount;
				}
			}
			
		    // remove duplicates in snds
		    for (newCount = 0; newCount < completeSndCount; newCount++)
			{
			    goodSound = TRUE;
			    soundID = completeSndArray[newCount];
			    for (count = 0; count < sndCount; count++)
				{
				    if (soundID == pSndArray[count])
					{
					    goodSound = FALSE;
					    break;
					}
				}
			    if (goodSound)
				{
				    pSndArray[sndCount++] = (XShortResourceID)soundID;
				}
			}
		    XBubbleSortArray((short *)pSndArray, (short)sndCount);
		}
	    XDisposePtr(completeSndArray);
	}
    return (short)sndCount;
}
示例#22
0
// Instruments 0 to MAX_INSTRUMENTS*MAX_BANKS are the standard MIDI instrument placements.
// This will create an internal instrument from and external instrument. If theX is non-null then it
// will use that data to create the GM_Instrument
GM_Instrument * PV_GetInstrument(XLongResourceID theID, void *theExternalX, INT32 patchSize)
{
    GM_Instrument		*theI, *theS;
    InstrumentResource	*theX;
    INT32				size;
    short int 			count;
    UBYTE				*theSound;
    KeySplit			theXSplit;
    CacheSampleInfo		sndInfo;
    LOOPCOUNT			i;
    INT32				theSampleID;

    theI = NULL;
    theX = (InstrumentResource *)theExternalX;
    if (theExternalX == NULL)
	{
	    theX = (InstrumentResource *)XGetAndDetachResource(ID_INST, theID, &patchSize);
	}
    if (theX)
	{
	    if (XGetShort(&theX->keySplitCount) < 2)	// if its 1, then it has no splits
		{
		    // get the sample ID from a short, values can be negative
		    // then allow conversion to take place.

		    // NOTE:	I know this is awfull, but if you change it things will break. The
		    //			internal ID values are all 32 bit signed, and some of the external
		    //			file structures are 16 bit signed.
		    theSampleID = (INT32)((short)XGetShort(&theX->sndResourceID));

		    theSound = (UBYTE *)PV_GetSampleFromID((INT32)theSampleID, &sndInfo);
		    if (theSound)
			{
			    theI = (GM_Instrument *)XNewPtr((INT32)sizeof(GM_Instrument));
			    if (theI)
				{
				    theI->u.w.theWaveform = (SBYTE *)theSound;

				    theI->disableSndLooping = TEST_FLAG_VALUE(theX->flags1, ZBF_disableSndLooping);
				    theI->playAtSampledFreq = TEST_FLAG_VALUE(theX->flags2, ZBF_playAtSampledFreq);
				    theI->doKeymapSplit = FALSE;
				    theI->notPolyphonic = TEST_FLAG_VALUE(theX->flags2, ZBF_notPolyphonic);
				    theI->avoidReverb = TEST_FLAG_VALUE(theX->flags1, ZBF_avoidReverb);
				    theI->useSampleRate = TEST_FLAG_VALUE(theX->flags1, ZBF_useSampleRate);
				    theI->sampleAndHold = TEST_FLAG_VALUE(theX->flags1, ZBF_sampleAndHold);
				    theI->useSoundModifierAsRootKey = TEST_FLAG_VALUE(theX->flags2, ZBF_useSoundModifierAsRootKey);
				    PV_GetEnvelopeData(theX, theI, patchSize);		// get envelope

				    theI->u.w.bitSize = sndInfo.bitSize;
				    theI->u.w.channels = sndInfo.channels;
				    theI->u.w.waveformID = XGetShort(&theX->sndResourceID);
				    theI->u.w.waveSize = sndInfo.waveSize;
				    theI->u.w.waveFrames = sndInfo.waveFrames;
				    theI->u.w.startLoop = sndInfo.loopStart;
				    theI->u.w.endLoop = sndInfo.loopEnd;

				    theI->masterRootKey = XGetShort(&theX->midiRootKey);
				    theI->panPlacement = theX->panPlacement;
				    theI->u.w.baseMidiPitch = (unsigned char)sndInfo.baseKey;
				    theI->u.w.sampledRate = sndInfo.rate;

				    // NOTE!! If ZBF_useSoundModifierAsRootKey is TRUE, then we are using
				    // the Sound Modifier data blocks as a root key replacement for samples in
				    // the particular split
				    theI->miscParameter1 = XGetShort(&theX->miscParameter1);
				    theI->miscParameter2 = XGetShort(&theX->miscParameter2);
				    if (theI->useSoundModifierAsRootKey)
					{
					    theI->enableSoundModifier = FALSE;
					    if (theI->miscParameter2 == 0)		// Forces a default value of 0 to 100
						{
						    theI->miscParameter2 = 100;
						}
					}
				    else
					{
					    theI->enableSoundModifier = TEST_FLAG_VALUE(theX->flags2, ZBF_enableSoundModifier);
					    theI->smodResourceID = theX->smodResourceID;

					    // Process sample in place
					    if ( (theI->enableSoundModifier) && (theI->u.w.bitSize == 8) && (theI->u.w.channels == 1) )
						{
#if DISPLAY_INSTRUMENTS
						    DPrint(drawDebug, "---->Processing instrument %ld with SMOD %ld\r", (INT32)theID, (INT32)theI->smodResourceID);
#endif
						    PV_ProcessSampleWithSMOD(theI->u.w.theWaveform,
									     theI->u.w.waveSize,
									     theI->u.w.waveformID,
									     theI->smodResourceID,
									     theI->miscParameter1,
									     theI->miscParameter2);
						}
					}
				}
			}
		}
	    else
		{	// Keysplits
#if DISPLAY_INSTRUMENTS
		    DPrint(drawDebug, "----->Processing %ld keysplits\r", (INT32)XGetShort(&theX->keySplitCount));
#endif
		    size = XGetShort(&theX->keySplitCount) * (INT32)sizeof(GM_KeymapSplit);
		    size += (INT32)sizeof(GM_KeymapSplitInfo);

		    theI = (GM_Instrument *)XNewPtr(size + (INT32)sizeof(GM_Instrument));
		    if (theI)
			{
			    theI->disableSndLooping = TEST_FLAG_VALUE(theX->flags1, ZBF_disableSndLooping);
			    theI->doKeymapSplit = TRUE;
			    theI->notPolyphonic = TEST_FLAG_VALUE(theX->flags2, ZBF_notPolyphonic);
			    theI->avoidReverb = TEST_FLAG_VALUE(theX->flags1, ZBF_avoidReverb);
			    theI->useSampleRate = TEST_FLAG_VALUE(theX->flags1, ZBF_useSampleRate);
			    theI->sampleAndHold = TEST_FLAG_VALUE(theX->flags1, ZBF_sampleAndHold);
			    theI->playAtSampledFreq = TEST_FLAG_VALUE(theX->flags2, ZBF_playAtSampledFreq);
			    theI->useSoundModifierAsRootKey = TEST_FLAG_VALUE(theX->flags2, ZBF_useSoundModifierAsRootKey);
			    PV_GetEnvelopeData(theX, theI, patchSize);		// get envelope

			    theI->u.k.KeymapSplitCount = XGetShort(&theX->keySplitCount);
			    theI->u.k.defaultInstrumentID = (XShortResourceID)XGetShort(&theX->sndResourceID);

			    theI->masterRootKey = XGetShort(&theX->midiRootKey);
			    theI->panPlacement = theX->panPlacement;

				// NOTE!! If ZBF_useSoundModifierAsRootKey is TRUE, then we are using
				// the Sound Modifier data blocks as a root key replacement for samples in
				// the particular split
			    theI->miscParameter1 = XGetShort(&theX->miscParameter1);
			    theI->miscParameter2 = XGetShort(&theX->miscParameter2);
			    if (theI->useSoundModifierAsRootKey)
				{
				    theI->enableSoundModifier = FALSE;
				    if (theI->miscParameter2 == 0)		// Forces a default value of 0 to 100
					{
					    theI->miscParameter2 = 100;
					}
				}
			    else
				{
				    theI->enableSoundModifier = TEST_FLAG_VALUE(theX->flags2, ZBF_enableSoundModifier);
				    theI->smodResourceID = theX->smodResourceID;
				}

			    for (count = 0; count < theI->u.k.KeymapSplitCount; count++)
				{
				    XGetKeySplitFromPtr(theX, count, &theXSplit);
				    theI->u.k.keySplits[count].lowMidi = theXSplit.lowMidi;
				    theI->u.k.keySplits[count].highMidi = theXSplit.highMidi;
				    theI->u.k.keySplits[count].miscParameter1 = theXSplit.miscParameter1;
				    if (theI->useSoundModifierAsRootKey && (theXSplit.miscParameter2 == 0))		// Forces a default value of 0 to 100
					{
					    theXSplit.miscParameter2 = 100;
					}
				    theI->u.k.keySplits[count].miscParameter2 = theXSplit.miscParameter2;

				    //					if (GM_IsInstrumentRangeUsed(theID, (INT16)theXSplit.lowMidi, (INT16)theXSplit.highMidi))
				    {
#if DISPLAY_INSTRUMENTS
					DPrint(drawDebug, "------->Keysplit %ld low %ld high %ld\r", (INT32)count,
					       (INT32)theXSplit.lowMidi,
					       (INT32)theXSplit.highMidi);
#endif
					theS =  PV_CreateInstrumentFromResource(theI, (XLongResourceID)theXSplit.sndResourceID);
					theI->u.k.keySplits[count].pSplitInstrument = theS;
					if (theS)
					    {
						theS->useSoundModifierAsRootKey = theI->useSoundModifierAsRootKey;
						theS->miscParameter1 = theXSplit.miscParameter1;
						if (theS->useSoundModifierAsRootKey && (theXSplit.miscParameter2 == 0))		// Forces a default value of 0 to 100
						    {
							theXSplit.miscParameter2 = 100;
						    }
						theS->miscParameter2 = theXSplit.miscParameter2;

						theS->masterRootKey = theI->masterRootKey;
						theS->avoidReverb = theI->avoidReverb;
						theS->volumeADSRRecord = theI->volumeADSRRecord;
						for (i = 0; i < theI->LFORecordCount; i++)
						    {
							theS->LFORecords[i] = theI->LFORecords[i];
						    }
						theS->LFORecordCount = theI->LFORecordCount;
						for (i = 0; i < theI->curveRecordCount; i++)
						    {
							theS->curve[i] = theI->curve[i];
						    }
						theS->curveRecordCount = theI->curveRecordCount;
						theS->LPF_frequency = theI->LPF_frequency;
						theS->LPF_resonance = theI->LPF_resonance;
						theS->LPF_lowpassAmount = theI->LPF_lowpassAmount;

						if (theS->useSoundModifierAsRootKey == FALSE)
						    {
							// Process sample in place
							if ( (theS->enableSoundModifier) && (theS->u.w.bitSize == 8) && (theS->u.w.channels == 1) )
							    {
#if DISPLAY_INSTRUMENTS
								DPrint(drawDebug, "----->Processing instrument %ld with SMOD %ld\r", (INT32)theID, (INT32)theI->smodResourceID);
#endif
								PV_ProcessSampleWithSMOD(	theS->u.w.theWaveform,
												theS->u.w.waveSize,
												theXSplit.sndResourceID,
												theS->smodResourceID,
												theS->miscParameter1,
												theS->miscParameter2);
							    }
						    }
					    }
				    }
				}
			}
		}
	    if (theExternalX == NULL)
		{
		    XDisposePtr((XPTR)theX);
		}
	}
#if DISPLAY_INSTRUMENTS
    if (theI)
	{
	    DPrint(drawDebug, "-------->INST info: masterRootKey %ld\r", (INT32)theI->masterRootKey);
	}
#endif
    return theI;
}
示例#23
0
// Given an mpeg bit encode rate, and a sample rate, this will return TRUE if
// this encoder can encode, or FALSE if it will not work.
XBOOL XIsValidMPEGSampleRateAndEncodeRate(XMPEGEncodeRate encodeRate, XFIXED sampleRate, 
		SndCompressionSubType subType, short int numChannels)
{
	XBOOL				safe;
	int					count;
	const int			TEMP_BUFFER_FRAMES = 2500;
	const int			TEMP_BUFFER_SIZE = TEMP_BUFFER_FRAMES * 2;
	XPTR				tempBuffer;
	GM_Waveform			*test;
	OPErr				err;
	XMPEGDecodedData	*stream;
	XFIXED				newSampleRate;

	numChannels; // we igore stereo samples for now.
	
	safe = FALSE;
	if (subType == CS_MPEG1)
	{
		newSampleRate = XGetClosestMPEGSampleRate(sampleRate, subType);
		if (sampleRate < newSampleRate)
		{
			return safe;
		}
	}

	tempBuffer = XNewPtr(TEMP_BUFFER_SIZE);
	if (tempBuffer)
	{
		for (count = 0; count < TEMP_BUFFER_SIZE; count++)
		{
			((XBYTE *)tempBuffer)[count] = (XBYTE)(127.0 * cos(count));
		}

		test = GM_NewWaveform();
		if (test)
		{
			XPTR			encodedData;
			UINT32			encodedBytes;

			test->theWaveform = tempBuffer;
			test->bitSize = 16;
			test->channels = 1;
			test->compressionType = C_NONE;
			test->sampledRate = sampleRate;
			test->waveSize = TEMP_BUFFER_SIZE;
			test->waveFrames = TEMP_BUFFER_FRAMES;

			err = XCompressMPEG(test, 
					XGetMPEGCompressionType(encodeRate),
					subType,
					NULL, NULL,
					&encodedData, &encodedBytes,
					NULL, NULL, NULL);

			if (err == NO_ERR)
			{
				// Have to open the stream simply to find out if the stream we just built is
				// valid.
				stream = XOpenMPEGStreamFromMemory(encodedData, encodedBytes, &err);
				if (stream && (err == NO_ERR))
				{
					safe = TRUE;
				}
				XCloseMPEGStream(stream);
			}
			XDisposePtr(encodedData);
			test->theWaveform = NULL;
			GM_FreeWaveform(test);
		}
		XDisposePtr(tempBuffer);
	}
	return safe;
}
示例#24
0
// Return a pointer to a 'snd' resource from its ID.
// If a handle is passed, then its assumed to be a snd resource and is used instead. It is not disposed
// of after use, so you must dispose of it
static void * PV_GetSampleData(XLongResourceID theID, XPTR useThisSnd, CacheSampleInfo *pInfo)
{
    XPTR			theData, thePreSound;
    char			*theSound;
    CacheSampleInfo	theSoundData;
    SampleDataInfo	newSoundInfo;
    INT32			size;

    theSound = NULL;
    if (useThisSnd)
	{
	    theData = useThisSnd;
	}
    else
	{
	    theData = XGetSoundResourceByID(theID, &size);
	}
    if (theData)
	{
	    // convert snd resource into a simple pointer of data with information

	    thePreSound = XGetSamplePtrFromSnd(theData, &newSoundInfo);

	    if (newSoundInfo.pMasterPtr != theData)
		{	// this means that XGetSamplePtrFromSnd created a new sample
		    XDisposePtr(theData);
		}

	    if (thePreSound)
		{
		    // validate loop points
		    if ((newSoundInfo.loopStart > newSoundInfo.loopEnd) ||
			(newSoundInfo.loopEnd > newSoundInfo.frames) ||
			((newSoundInfo.loopEnd - newSoundInfo.loopStart) < MIN_LOOP_SIZE) )
			{
				// disable loops
			    newSoundInfo.loopStart = 0;
			    newSoundInfo.loopEnd = 0;
			}
		    theSoundData.theID = (short int)theID;
		    theSoundData.waveSize = newSoundInfo.size;
		    theSoundData.waveFrames = newSoundInfo.frames;
		    theSoundData.loopStart = newSoundInfo.loopStart;
		    theSoundData.loopEnd = newSoundInfo.loopEnd;
		    theSoundData.baseKey = newSoundInfo.baseKey;
		    theSoundData.bitSize = (char)newSoundInfo.bitSize;
		    theSoundData.channels = (char)newSoundInfo.channels;
		    theSoundData.rate = newSoundInfo.rate;

#if DISPLAY_INSTRUMENTS
		    DPrint(drawDebug, "---->Getting 'snd' ID %ld rate %lX loopstart %ld loopend %ld basekey %ld\r", (INT32)theID,
			   theSoundData.rate, theSoundData.loopStart,
			   theSoundData.loopEnd, (INT32)theSoundData.baseKey);
#endif
		    theSoundData.pSampleData = thePreSound;
		    theSoundData.pMasterPtr = newSoundInfo.pMasterPtr;
		    theSoundData.cacheBlockID = ID_INST;
		    *pInfo = theSoundData;
		    theSound = (char *)thePreSound;
		}
	}
    return theSound;
}
示例#25
0
// This will encode an MPEG stream from a formatted GM_Waveform
OPErr XCompressMPEG(GM_Waveform const* wave, 
					SndCompressionType compressionType,
					SndCompressionSubType compressionSubType,
					XCompressStatusProc proc, void* procData,
					XPTR* pCompressedData, XDWORD* pCompressedBytes,
					XDWORD* pFrameBufferCount, XDWORD* pFrameBufferBytes,	//MOE: we don't really need these
					XDWORD* startFrame)
{
XMPEGEncodeRate		const encodeRate = XGetMPEGEncodeRate(compressionType);
GM_Waveform			hackedWave;
XMPEGEncodeRate		hackedEncodeRate;
OPErr				err;
XMPEGEncodeData*	mpegEncode;
unsigned long		originalOffset;

	// capture any original silence prior to encoding
	originalOffset = PV_ScanForAudioData((short int *)wave->theWaveform,
										wave->waveSize,
										wave->channels);

	hackedWave = *wave;
	XGetClosestMPEGSampleRateAndEncodeRate(wave->sampledRate, encodeRate,
											&hackedWave.sampledRate,
											&hackedEncodeRate,
											compressionSubType
											);

	// MOE: The above code depends on the fact that XMPEGEncodeRate{}s are defined to
	// equal their bitrates divided by 1024 (defined in X_Formats.h).

	*pCompressedData = NULL;
	mpegEncode = XOpenMPEGEncodeStreamFromMemory(&hackedWave, hackedEncodeRate, &err);
	if (mpegEncode)
	{
	OPErr				closeErr;
		
		while (TRUE)
		{
			err = XProcessMPEGEncoder(mpegEncode);
			if (err != NO_ERR)
			{
				if (err == STREAM_STOP_PLAY) err = NO_ERR;
				else BAE_ASSERT(FALSE);
				break;
			}
			
			if (proc && (*proc)(procData,
								mpegEncode->currentFrameBuffer,
								mpegEncode->maxFrameBuffers))
			{
				err = ABORTED_PROCESS;
				break;
			}
		}
		
		if (pFrameBufferBytes)
		{
			*pFrameBufferBytes = mpegEncode->frameBufferSizeInBytes;
		}
		if (pFrameBufferCount)
		{
			*pFrameBufferCount = mpegEncode->maxFrameBuffers;
		}

		closeErr = XCloseMPEGEncodeStream(mpegEncode, pCompressedData, pCompressedBytes);
		if (err == NO_ERR)
		{
			err = closeErr;
		}
		if ((err == NO_ERR) && startFrame)
		{
			// XProcessMPEGEncoder() seems to prepend some number zero samples to the waveform.
			// Scan the first frame buffer for the first nonzero sample and
			// set *startFrame to the offset to it.
#if 0
			*startFrame = 0;
#else
			*startFrame =
				PV_ScanForAudioDataFromMPEG(*pCompressedData, *pCompressedBytes,
											pFrameBufferCount, &err);
			if (*startFrame > originalOffset)
			{
				*startFrame -= originalOffset;
			}
#endif
		}

		if (err != NO_ERR)
		{
			XDisposePtr(*pCompressedData);
			*pCompressedData = NULL;
		}
	}
	return err;
}
示例#26
0
// Scan the midi file and determine which instrument that need to be loaded and load them.
OPErr GM_LoadSongInstruments(GM_Song *theSong, XShortResourceID *pArray, XBOOL loadInstruments)
{
    register INT32	count, loadCount, instCount, newCount;
    XBOOL			loopSongSave;
    OPErr			theErr;
    SBYTE			remapUsedSaved[MAX_INSTRUMENTS];
    SBYTE			remapUsed[MAX_INSTRUMENTS];

#if DISPLAY_INSTRUMENTS
    {
	char text[256];

	drawDebug = DNew((char *)"\pInstruments to load");
	sprintf(text, "SONG %ld debug file", (INT32)theSong->songID);
#if DISPLAY_INSTRUMENTS_FILE
	DAttachFile(drawDebug, ctop(text));
	DPrint(drawDebug, "Writing output to file: Ô%pÕ\r", text);
#endif
    }
#endif
    // Set the sequencer to mark instruments only
    theErr = NO_ERR;

    theSong->pUsedPatchList = (SBYTE *)XNewPtr((MAX_INSTRUMENTS*MAX_BANKS*128L) / 8);
    if (theSong->pUsedPatchList)
	{
	    for (count = 0; count < MAX_INSTRUMENTS*MAX_BANKS; count++)
		{
		    theSong->remapArray[count] = count;
		    if (pArray)
			{
			    pArray[count] = (XShortResourceID)-1;
			}
		}
	    for (count = 0; count < MAX_CHANNELS; count++)
		{
		    theSong->firstChannelBank[count] = 0;
		    theSong->firstChannelProgram[count] = -1;
		}
	    theErr = PV_ConfigureMusic(theSong);
	    if (theErr == NO_ERR)
		{
		    if (theSong->defaultPercusionProgram == -1)
			{
			    theSong->channelBank[PERCUSSION_CHANNEL] = 0;
			    theSong->firstChannelBank[PERCUSSION_CHANNEL] = 0;
			}
		    else
			{
			    if (theSong->defaultPercusionProgram)
				{
				    theSong->firstChannelProgram[PERCUSSION_CHANNEL] = theSong->defaultPercusionProgram;
				    GM_SetUsedInstrument(theSong, (XLongResourceID)theSong->defaultPercusionProgram, 60, TRUE);
				}
			}

		    theSong->AnalyzeMode = SCAN_SAVE_PATCHES;
		    theSong->SomeTrackIsAlive = TRUE;

		    loopSongSave = theSong->loopSong;
		    theSong->loopSong = FALSE;
		    while (theSong->SomeTrackIsAlive)
			{
			    theErr = PV_ProcessMidiSequencerSlice(NULL, theSong);
			    if (theErr)
				{
				    break;
				}
			}
		    theSong->AnalyzeMode = SCAN_NORMAL;
		    theSong->loopSong = loopSongSave;

		    if (theErr == NO_ERR)
			{
				// are we trying to load any instruments? This is for the case were there are no program changes. We must do something
			    newCount = FALSE;
			    for (count = 0; count < MAX_CHANNELS; count++)
				{
				    if (count != PERCUSSION_CHANNEL)	// only look at non percussion channels
					{
					    if (theSong->firstChannelProgram[count] != -1)
						{
						    newCount = TRUE;
						    break;
						}
					}
				}
			    if (newCount == FALSE)
				{	// there have been no program changes. So set up just the piano in all channels
				    for (count = 0; count < MAX_CHANNELS; count++)
					{
					    theSong->firstChannelProgram[count] = 0;
					    theSong->channelProgram[count] = 0;
					}
				    GM_SetUsedInstrument(theSong, 0, -1, TRUE);		// load the entire piano
				}
#if DISPLAY_INSTRUMENTS
			    DPrint(drawDebug, "Loading instruments:\r");
#endif
			    instCount = 0;
			    for (count = 0; count < MAX_INSTRUMENTS*MAX_BANKS; count++)
				{
				    // instrument needs to be loaded
				    if (GM_IsInstrumentUsed(theSong, count, -1))
					{
#if DISPLAY_INSTRUMENTS
					    DPrint(drawDebug, "Instrument %ld: ", (INT32)count);
#endif
					    loadCount = theSong->instrumentRemap[count];
					    if (loadCount == -1)
						{
						    loadCount = count;
						}
#if DISPLAY_INSTRUMENTS
					    else
						{
						    DPrint(drawDebug, "remapped to %ld ", (INT32)loadCount);
						}
#endif
#if DISPLAY_INSTRUMENTS
					    DPrint(drawDebug, "loading instrument %ld\r", loadCount);
#endif
					    if (pArray)
						{
						    pArray[instCount++] = (short)loadCount;
						}

					    if (loadInstruments)
						{
						    if (loadCount != count)
							{
							    GM_GetInstrumentUsedRange(theSong, loadCount, remapUsedSaved);		// save
							    GM_GetInstrumentUsedRange(theSong, count, remapUsed);
							    GM_SetInstrumentUsedRange(theSong, loadCount, remapUsed);
							}
						    theErr = GM_LoadInstrument(theSong, loadCount);
						    if (theErr != NO_ERR)
							{	// if the instrument is some other bank, then go back to the standard GM bank before failing
							    if (loadCount > MAX_INSTRUMENTS)
								{
#if DISPLAY_INSTRUMENTS
								    DPrint(drawDebug, "Failed loading extra bank instrument %ld, falling back to GM.\r", loadCount);
#endif
								    newCount = (loadCount % MAX_INSTRUMENTS);
								    newCount += ((loadCount / MAX_INSTRUMENTS) & 1) * MAX_INSTRUMENTS;
								    loadCount = newCount;

#if DISPLAY_INSTRUMENTS
								    DPrint(drawDebug, "Loading instrument %ld\r", loadCount);
#endif
								    theErr = GM_LoadInstrument(theSong, loadCount);
								    if (theSong->ignoreBadInstruments)
									{
									    theErr = NO_ERR;
									}
								}
							    else
								{	// we are in GM, so check our ignore flag
								    if (theSong->ignoreBadInstruments)
									{
									    theErr = NO_ERR;
									}
								}
							}
						    if (loadCount != count)
							{
							    GM_SetInstrumentUsedRange(theSong, loadCount, remapUsedSaved);		// save
							}
						    if (theErr)
							{
#if DISPLAY_INSTRUMENTS
							    DPrint(drawDebug, "Failed to load instrument %ld (%ld)\r", (INT32)loadCount, (INT32)theErr);
#endif
							    break;
							}
						    theErr = GM_RemapInstrument(theSong, loadCount, count);	// remap from: to
						    // we are in GM, so check our ignore flag
						    if (theSong->ignoreBadInstruments)
							{
							    theErr = NO_ERR;
							}
						}
					}
				}
			}
		}

	    if (theErr != NO_ERR)
		{
		    GM_UnloadSongInstruments(theSong);		// ignore error
		}
	    XDisposePtr(theSong->pUsedPatchList);
	    theSong->pUsedPatchList = NULL;
	}
    else
	{
	    theErr = MEMORY_ERR;
	}
#if DISPLAY_INSTRUMENTS
    DPrint(drawDebug, "\rClick to exit");
    while (Button() == FALSE) {};
    while (Button()) {};
    FlushEvents(mDownMask, 0);
    DCopy(drawDebug);
    DDispose(drawDebug);
#endif

    return theErr;
}
示例#27
0
OPErr GM_UnloadInstrument(GM_Song *pSong, XLongResourceID instrument)
{
    register GM_Instrument		*theI;
    register GM_KeymapSplit		*k;
    register OPErr				theErr;
    register short int			splitCount;

    theErr = BAD_INSTRUMENT;
    if ( (instrument >= 0) && (instrument < (MAX_INSTRUMENTS*MAX_BANKS)) )
	{
	    if (pSong)
		{
		    theErr = NO_ERR;
		    theI = pSong->instrumentData[instrument];
		    if (theI)
			{
			    if (theI->processingSlice == FALSE)
				{
				    theI->usageReferenceCount--;		// decrement reference count
				    if (theI->usageReferenceCount == 0)
					{
					    pSong->instrumentData[instrument] = NULL;	// do this first so other threads won't walk into
					    // bad news land
					    if (theI->doKeymapSplit)
						{
						    k = theI->u.k.keySplits;
						    for (splitCount = 0; splitCount < theI->u.k.KeymapSplitCount; splitCount++)
							{
							    if (k->pSplitInstrument)
								{
								    if (k->pSplitInstrument->u.w.theWaveform)
									{
									    PV_FreeCacheEntryFromPtr(k->pSplitInstrument->u.w.theWaveform);
									}
								    XDisposePtr(k->pSplitInstrument);
								}
							    k++;
							}
						}
					    else
						{
						    if (theI->u.w.theWaveform)
							{
							    PV_FreeCacheEntryFromPtr(theI->u.w.theWaveform);
							}
						}
					    XDisposePtr((void FAR *)theI);
					}

				    else
					{ 	// duplicate reference
					    theErr = NO_ERR;
					}
				}
			    else
				{
				    theErr = STILL_PLAYING;
				}
			}
		    //			else
		    //			{
		    //				theErr = BAD_INSTRUMENT;
		    //			}
		}
	    else
		{
		    theErr = NOT_SETUP;
		}
	}
    else
	{
	    theErr = PARAM_ERR;
	}
    return theErr;
}
示例#28
0
// Given a song ID and two arrays, this will return the INST resources ID and the 'snd ' resource ID
// that are needed to load the song terminated with a -1.
// Will return 0 for success or 1 for failure
OPErr XGetSongInstrumentList(XShortResourceID theSongID, XShortResourceID *pInstArray, short int maxInstArraySize, 
			     XShortResourceID *pSndArray, short int maxSndArraySize)
{
    long				count, instCount, sndCount, newCount, completeSndCount;
    XShortResourceID	soundID;
    SongResource		*theSong;
    XShortResourceID	completeSndArray[MAX_SAMPLES];
    XShortResourceID	completeInstArray[MAX_INSTRUMENTS * MAX_BANKS];
    XBOOL				goodSound;
    OPErr				theErr;
    long				size;

    theErr = NO_ERR;
    if ( (pInstArray) && (pSndArray) )
	{
	    for (count = 0; count < maxInstArraySize; count++)
		{
		    pInstArray[count] = (XShortResourceID)-1;
		    completeInstArray[count] = (XShortResourceID)-1;
		}
	    for (count = 0; count < maxSndArraySize; count++)
		{
		    pSndArray[count] = (XShortResourceID)-1;
		    completeSndArray[count] = (XShortResourceID)-1;
		}
	    theSong = (SongResource *)XGetAndDetachResource(ID_SONG, theSongID, &size);
	    if (theSong)
		{
		    instCount = GM_GetUsedPatchlist(theSong, NULL, 0L, completeInstArray, &theErr);
		    if (instCount && (theErr == 0) )
			{
				// remove duplicates in inst
			    sndCount = 0;
			    for (newCount = 0; newCount < instCount; newCount++)
				{
				    goodSound = TRUE;
				    soundID = completeInstArray[newCount];
				    for (count = 0; count < sndCount; count++)
					{
					    if (soundID == pInstArray[count])
						{
						    goodSound = FALSE;
						    break;
						}
					}
				    if (goodSound)
					{
					    pInstArray[sndCount++] = (XShortResourceID)soundID;
					}
				}
			    instCount = sndCount;
			    XBubbleSortArray((short *)pInstArray, (short)instCount);

			    completeSndCount = 0;
			    for (count = 0; count < instCount; count++)
				{
				    newCount = XCollectSoundsFromInstrumentID(pInstArray[count], 
									      &completeSndArray[completeSndCount], 128);
				    completeSndCount += newCount;
				}
				
				// remove duplicates in snds
			    sndCount = 0;
			    for (newCount = 0; newCount < completeSndCount; newCount++)
				{
				    goodSound = TRUE;
				    soundID = completeSndArray[newCount];
				    for (count = 0; count < sndCount; count++)
					{
					    if (soundID == pSndArray[count])
						{
						    goodSound = FALSE;
						    break;
						}
					}
				    if (goodSound)
					{
					    pSndArray[sndCount++] = (XShortResourceID)soundID;
					}
				}
			    XBubbleSortArray((short *)pSndArray, (short)sndCount);
			}
		    else
			{
			    theErr = BAD_MIDI_DATA;
			}
		}
	    XDisposePtr((XPTR)theSong);
	}
    return theErr;
}
示例#29
0
XERR XCopySndResources(XShortResourceID *pSndCopy, short int sndCount, XFILE readFileRef, 
		       XFILE writeFileRef, XBOOL protect, XBOOL copyNames)
{
    short int		count, resCount;
    XPTR			pData;
    short int		theID;
    char			theName[256];
    long			size;
    long			soundTypes[] = {ID_SND, ID_ESND, ID_CSND};

    if (sndCount && pSndCopy)
	{
	    XFileUseThisResourceFile(readFileRef);		/* from resource file */
	    for (count = 0; count < sndCount; count++)
		{
		    theID = pSndCopy[count];
			
		    // determine if the resource is already in the written file
		    XFileUseThisResourceFile(writeFileRef);
		    pData = XGetAndDetachResource(ID_SND, theID, &size);
		    if (pData == NULL)
			{
			    pData = XGetAndDetachResource(ID_ESND, theID, &size);
			}
		    if (pData == NULL)
			{
			    pData = XGetAndDetachResource(ID_CSND, theID, &size);
			}
		    XDisposePtr(pData);
		    if (pData == NULL)			// check to see that its not there already!!
			{
			    for (resCount = 0; resCount < 3; resCount++)
				{
				    XFileUseThisResourceFile(readFileRef);		/* from resource file */
				    pData = XGetFileResource(readFileRef, soundTypes[resCount], theID, theName, &size);
				    if (pData)
					{
					    if (copyNames == FALSE)
						{
						    theName[0] = 0;
						}

					    XFileUseThisResourceFile(writeFileRef);
					    if (protect && (soundTypes[resCount] == ID_SND))
						{
						    XEncryptData(pData, size);
						    XAddResource(ID_ESND, theID, theName, pData, size);
						}
					    else
						{
						    XAddResource(soundTypes[resCount], theID, theName, pData, size);
						}
					    XDisposePtr(pData);
					}
				}
			}
		    else
			{
			    XDisposePtr(pData);
			}
		}
	}
    return 0;
}
示例#30
0
XERR XCopySongMidiResources(XLongResourceID theSongID, XFILE readFileRef, 
			    XFILE writeFileRef, XBOOL protect, XBOOL copyNames)
{
    XPTR			pData;
    SongResource	*theSong;
    long			songSize;
    XResourceType	theDataType;
    short int		theID;
    char			theName[256], theSongName[256];
    unsigned long	dataSize, newSize;
    XPTR			newMidiData;

    XFileUseThisResourceFile(readFileRef);		// from resource file
    theSong = (SongResource *)XGetFileResource(readFileRef, ID_SONG, theSongID, theSongName, &songSize);
    if (theSong)
	{
	    theID = XGetSongResourceObjectID(theSong);

	    if (protect)
		{
		    pData = XGetMidiData(theID, (long *)&dataSize, &theDataType);
		    if (pData)
			{
			    newMidiData = XCompressAndEncrypt(pData, dataSize, &newSize);
			    if (newMidiData)
				{
				    theDataType = ID_ECMI;
				    XDisposePtr(pData);
				    pData = newMidiData;
				}
			    else
				{
				    theDataType = ID_MIDI;
				}
			}
		}
	    else
		{
		    theDataType = ID_CMID;
		    pData = XGetFileResource(readFileRef, ID_CMID, theID, theName, (long *)&dataSize);
		    if (pData == NULL)
			{
			    theDataType = ID_ECMI;
			    pData = XGetFileResource(readFileRef, ID_ECMI, theID, theName, (long *)&dataSize);
			}
		    if (pData == NULL)
			{
			    theDataType = ID_EMID;
			    pData = XGetFileResource(readFileRef, ID_EMID, theID, theName, (long *)&dataSize);
			}
		    if (pData == NULL)
			{
			    theDataType = ID_MIDI;
			    pData = XGetFileResource(readFileRef, ID_MIDI, theID, theName, (long *)&dataSize);
			}
		    if (pData == NULL)
			{
			    theDataType = ID_MIDI;		// convert it to the new type
			    pData = XGetFileResource(readFileRef, ID_MIDI_OLD, theID, theName, (long *)&dataSize);
			}
		}
	    if (pData)
		{
		    // write midi resource
		    XFileUseThisResourceFile(writeFileRef);
		    if (copyNames == FALSE)
			{
			    theName[0] = 0;
			}
		    XAddResource(theDataType, theID, theName, pData, (long)dataSize);
		    XDisposePtr(pData);

		    // write song resource
		    XFileUseThisResourceFile(readFileRef);

		    if (protect)
			{
			    XSetSongLocked(theSong, TRUE);
			}

		    XFileUseThisResourceFile(writeFileRef);
		    XAddResource(ID_SONG, theID, theName, theSong, songSize);
		    XDisposePtr(theSong);
		}
	}
    return 0;
}