⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmatone.c

📁 用于移动设备上的java虚拟机源代码
💻 C
字号:
/* * @(#)mmatone.c	1.29 02/10/01 @(#) * * Copyright (c) 1996-2002 Sun Microsystems, Inc.  All rights reserved. * PROPRIETARY/CONFIDENTIAL * Use is subject to license terms. */#include <kni.h>#include <midpMalloc.h>#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <time.h>#include "audiornd.h"#define MAXCHNL 4#define SILENCE -1#define INSEQ_SET_VOLUME -8#define MAXVAL  32767#define SCALE   100typedef struct {    int adptr;    int *sequences;    int seqlen;    int curNote;    int sampleLeft;    int vol;    int curMTime;    pthread_t tid;    char pID;    char closed;      char singleTone; /* 1: single tone; 2:tone sequence; 0 unused */    char play;    char prePlay;    char gain;}TONEDATA;  TONEDATA tonepool[MAXCHNL];static char initTonePool = 1;pthread_mutex_t theMutex;/* ======= For tones */#define SAMPLE_LENGTH 125 /* tone data is in format of 8k/16bit/mono/signed  */int  K[128] = {122309, 115444, 108965, 102849,               97077, 91628, 86486, 81632,                77050, 72725, 68644, 64791,                61154, 57722, 54482, 51425,                48538, 45814, 43243, 40816,                38525, 36363, 34322, 32395,                30577, 28861, 27241, 25712,                24269, 22907, 21621, 20408,                19262, 18181, 17161, 16198,                15289, 14430, 13621, 12856,                12135, 11453, 10811, 10204,                9631, 9091, 8580, 8099,                7644, 7215, 6810, 6428,                6067, 5727, 5405, 5102,                4816, 4545, 4290, 4049,                3822, 3608, 3405, 3214,                3034, 2863, 2703, 2551,                2408, 2273, 2145, 2025,                1911, 1804, 1703, 1607,                1517, 1432, 1351, 1275,                1204, 1136, 1073, 1012,                956, 902, 851, 804,                758, 716, 676, 638,                602, 568, 536, 506,                478, 451, 426, 402,                379, 358, 338, 319,                301, 284, 268, 253,                239, 225, 213, 201,                190, 179, 169, 159,                150, 142, 134, 127,                119, 113, 106, 100,                95, 89, 84, 80};void injectNativeEvent(int playerID, int curMTime);/*=============================== * Utility functions *=============================== *//* * This function is always called from midp main native thread */TONEDATA* getToneChnl() {  int i;  TONEDATA *ret = NULL;  if (initTonePool == 1) {    initTonePool = 0;    memset(tonepool, 0, MAXCHNL*sizeof(TONEDATA));    pthread_mutex_init(&theMutex, NULL);  }    pthread_mutex_lock(&theMutex);  for (i = 0; i < MAXCHNL; i++) {    if (tonepool[i].singleTone == 0) {      /* for single tone, sequences is not freed when it completes, 	 so need to free here */      if (tonepool[i].sequences != NULL){	midpFree(tonepool[i].sequences);      }      memset(&tonepool[i], 0, sizeof(TONEDATA));      ret = &tonepool[i];      break;    }  }    pthread_mutex_unlock(&theMutex);  return (ret);}void tonegen(char *data, int len, TONEDATA *td) {  int toWrite, written;  int note, durInSamples, phase1, phase2;  int tonedata;  int amplitude = td->vol * (td->gain & 0x7f) / 100;  durInSamples = td->sequences[td->curNote+1];  written = durInSamples - td->sampleLeft;  toWrite = len >> 1;  if (toWrite > td->sampleLeft)    toWrite = td->sampleLeft;    note = td->sequences[td->curNote];  if (note == SILENCE || amplitude == 0) {    memset(data, 0, toWrite << 1);  } else {    long x, t, slope, tmp;    int KK, hKK, qKK;    KK = K[note];    hKK = KK >> 1;    qKK = KK >> 2;    phase1 = durInSamples / 10;  /* 10% attack */    phase2 = durInSamples * 3 / 4; /* 25% decay */    slope = (amplitude) * SCALE * 4 / KK;    for (x = written; x < (written + toWrite); x++) {      t = x * SAMPLE_LENGTH;            /* map to within k */      t = t % KK ;            /* triangle wave: 4 discrete fcn's based on phase */      if (t <= qKK) {	tonedata = (int)(slope * t / SCALE);      } else if (t <= hKK) {	tonedata = (int)((hKK-t) * slope / SCALE);      } else if (t <= 3*qKK) {	tonedata = (int)(-1 * (t-hKK) * slope / SCALE);      } else {	tonedata = (int)(-1 * (KK-t) * slope / SCALE);      }      if (tonedata > MAXVAL) {	  tonedata = MAXVAL;      }      if (tonedata < -1 * MAXVAL) {	  tonedata = -1 * MAXVAL;      }      /* attack & decay */      if (x < phase1) { 	tonedata = tonedata * x / phase1;      } else if (x > phase2) { 	tonedata = tonedata * (durInSamples - 1 - x) / (durInSamples - phase2);      }#ifdef BIG_ENDIAN      data[2*(x-written)] = (char)((tonedata >> 8) & 0xff);      data[2*(x-written)+1] = (char)(tonedata & 0xff);#else  /* LITTLE_ENDIAN */      data[2*(x-written)] = (char)(tonedata & 0xff);      data[2*(x-written)+1] = (char)((tonedata >> 8) & 0xff);#endif    }      } /* else */    audioWrite(td->adptr, 0, toWrite << 1);  td->sampleLeft -= toWrite;}/* * this is the main function for tone/tone seq generation. * It runs on a separate native thread. */void * tonemain(void *arg) {    TONEDATA *td = (TONEDATA *)arg;    struct timespec interval;    char *data;    int len = 8000 * 16 * 1 / 8 / 32 & ~3;         interval.tv_sec = 0;    interval.tv_nsec = 16000000;    while (1) {	if (td->closed == 1)	    break;	if (td->play == 0) {	    if (td->prePlay == 1)		audioCommon(td->adptr, PAUSE, 0);	    td->prePlay = td->play;	    nanosleep((const struct timespec *)&interval, NULL);	    continue;	}	if (td->prePlay == 0) {	    td->prePlay = 1;	    audioCommon(td->adptr, RESUME, 0);	}	if (td->sampleLeft > 0) {	    data = getNextAvailBuf(td->adptr, len);	    if (data == NULL) {		nanosleep((const struct timespec *)&interval, NULL);		continue;	    }	    	    tonegen(data, len, td);	} else {	    if (td->singleTone == 1)		break;	    td->curNote += 2;	    if (td->curNote < td->seqlen) {		if (td->sequences[td->curNote] == INSEQ_SET_VOLUME) {		    td->gain = (char)(td->sequences[td->curNote+1] & 0x7f);		    continue;		}				if (td->curNote > 0)		    td->curMTime += td->sequences[td->curNote-1] >> 3;				td->sampleLeft = td->sequences[td->curNote+1];	    } else { /* EOM */		if (td->curNote > 0)		    td->curMTime += td->sequences[td->curNote-1] >> 3;				td->play = 0;		td->gain = 100;		while (audioCommon(td->adptr, DRAIN, 0) == 0)		    nanosleep((const struct timespec *)&interval, NULL);		injectNativeEvent((int)(td->pID), (int)(td->curMTime));	    }	}    }    if (td->singleTone == 1) {#ifdef SOLARIS	/**	 * On Solaris, drain has to be done explicitly.	 * On Linux, close imply a drain.	 */	while (audioCommon(td->adptr, DRAIN, 0) == 0)	    nanosleep((const struct timespec *)&interval, NULL);#endif	audioCommon(td->adptr, CLOSE, 0);	/* release this slot in tonepool */	pthread_mutex_lock(&theMutex);	td->singleTone = 0;	pthread_mutex_unlock(&theMutex);    }         return NULL;}/*========================================================================= * FUNCTION:      nPlayTone(III)I * CLASS:         javax.microedition.media.Manager * TYPE:          static virtual native function * OVERVIEW:      play a single tone * INTERFACE (operand stack manipulation): *   parameters:  note     the note to be played *                duration the duration of the note *                volume   the volume *   returns:     status. 1 succeeded; <= 0 failed. *=======================================================================*/KNIEXPORT KNI_RETURNTYPE_INT Java_javax_microedition_media_Manager_nPlayTone(KNITRAPS) {  TONEDATA *td;  int note, dur, vol;    note = (int)KNI_GetParameterAsInt(1);  dur = (int)KNI_GetParameterAsInt(2);  vol = (int)KNI_GetParameterAsInt(3);  td = getToneChnl();  if (td == NULL) {      KNI_ReturnInt(0);  }  if (vol < 0) {    vol = 0;  } else if (vol > 100) {    vol = MAXVAL;  } else {    vol = (vol * MAXVAL)/100;  }  if (vol == 0)    KNI_ReturnInt(1);  dur <<= 3;  #ifdef BIG_ENDIAN  td->adptr = audioOpen(8000, 16, 1, MMAFMT_SIGNED, MMAFMT_BIG);#else /* LITTLE_ENDIAN */  td->adptr = audioOpen(8000, 16, 1, MMAFMT_SIGNED, MMAFMT_LITTLE);#endif  if (td->adptr != 0) {    int reterr;        td->sequences = (int *)midpMalloc(2*sizeof(int));    td->seqlen = 2;    td->sequences[0] = note;    td->sequences[1] = dur;    td->sampleLeft = dur;    td->vol = vol;    td->gain = 100;    td->singleTone = 1;    td->play = td->prePlay = 1;    reterr = pthread_create(&(td->tid), NULL, tonemain, (void *)td);    if (reterr != 0 ) {      printf("error in creating new thread %d \n", reterr);    }     KNI_ReturnInt(1);  }   td->singleTone = 0;  KNI_ReturnInt(0);}/*========================================================================= * FUNCTION:      toneInit(I)I * CLASS:         com.sun.mmedia.TonePlayer * TYPE:          virtual native function * OVERVIEW:      initialization for tone seq playback * INTERFACE (operand stack manipulation): *   parameters:  playerID  the global playerID for this tone player *   returns:     the pointer to the toneseq data structure; <= 0 failed. *=======================================================================*/KNIEXPORT KNI_RETURNTYPE_INT Java_com_sun_mmedia_TonePlayer_toneInit(KNITRAPS) {    int playerID = (int)KNI_GetParameterAsInt(1);        TONEDATA *ts;    ts = getToneChnl();    if (ts == NULL)	KNI_ReturnInt(0);#ifdef BIG_ENDIAN    ts->adptr = audioOpen(8000, 16, 1, MMAFMT_SIGNED, MMAFMT_BIG);#else /* LITTLE_ENDIAN */    ts->adptr = audioOpen(8000, 16, 1, MMAFMT_SIGNED, MMAFMT_LITTLE);#endif    if (ts->adptr != 0) {	int reterr;	ts->pID = (char)(playerID & 0x7f);	ts->singleTone = 2;	ts->vol = MAXVAL;	ts->gain = 100;	reterr = pthread_create(&(ts->tid), NULL, tonemain, (void *)ts);    	if (reterr == 0 ) {	    KNI_ReturnInt((jint)ts);	} else {	    printf("failed to create new thread \n");	}    }        ts->singleTone = 0;    KNI_ReturnInt(0);}/*======================================================================== * FUNCTION:      toneSetSeq(I[I)V * CLASS:         com.sun.mmedia.TonePlayer * TYPE:          virtual native function * OVERVIEW:      pass the tone sequence from java to native * INTERFACE (operand stack manipulation): *   parameters:  ad       the pointer to the toneseq data structure *                toneseq  the int array that holds the tone sequence *   returns:     nothing *======================================================================*/KNIEXPORT KNI_RETURNTYPE_VOID Java_com_sun_mmedia_TonePlayer_toneSetSeq(KNITRAPS){    int pts = KNI_GetParameterAsInt(1);    int p, i;        TONEDATA *ts = (TONEDATA *)(pts);    if ( ts == NULL) {	KNI_ReturnVoid();    }    if ( ts->sequences != NULL) {	midpFree(ts->sequences);	ts->sequences = NULL;    }    KNI_StartHandles(1);    KNI_DeclareHandle(arrHandle);    KNI_GetParameterAsObject(2, arrHandle);    ts->seqlen = KNI_GetArrayLength(arrHandle);    ts->sequences = (int *)midpMalloc(ts->seqlen * sizeof(int));    for ( i = 0; i < ts->seqlen/2; i++) {	p = i << 1;	ts->sequences[p] = KNI_GetIntArrayElement(arrHandle, p);	if (ts->sequences[p] == INSEQ_SET_VOLUME)	    ts->sequences[p+1] = KNI_GetIntArrayElement(arrHandle, p+1);	else	    ts->sequences[p+1] = KNI_GetIntArrayElement(arrHandle, p+1) << 3;    }    ts->curNote = -2;    ts->curMTime = 0;    ts->play = ts->prePlay = 0;    ts->sampleLeft = 0;    ts->gain = 100;    KNI_EndHandles();    KNI_ReturnVoid();}/*========================================================================= * FUNCTION:      toneCommon(III)I * CLASS:         com.sun.mmedia.TonePlayer * TYPE:          virtual native function * OVERVIEW:      common utility functions for tone player * INTERFACE (operand stack manipulation): *   parameters:  ad    the pointer to the toneseq data structure *                code  opcode for a particular tone operation *                param user defined  parameter *   returns:     status. <= 0 failed. *=======================================================================*/KNIEXPORT KNI_RETURNTYPE_INT Java_com_sun_mmedia_TonePlayer_toneCommon(KNITRAPS){    int param = KNI_GetParameterAsInt(3);    int code = KNI_GetParameterAsInt(2);    int pts = KNI_GetParameterAsInt(1);        TONEDATA *ts = (TONEDATA *)(pts);    int ret = 1;        if ( ts == NULL ) {	KNI_ReturnInt(0);    }        switch (code) {    case RESUME:	ts->play = 1;	break;	    case PAUSE:      {	struct timespec interval;    	ts->play = 0;	/* sleep 40 ms to wait for that the flag play=0 takes effective in	   the play thread to avoid potential race condition */	interval.tv_sec = 0;	interval.tv_nsec = 40000000;	nanosleep((const struct timespec *)&interval, NULL);      }	break;    case SET_VOLUME:	param = (param * MAXVAL)/100;	ts->vol = param;	break;    case CLOSE:	ts->closed = 1;	pthread_join(ts->tid, NULL); /* wait for the tone thread dead */	audioCommon(ts->adptr, FLUSH, 0);	audioCommon(ts->adptr, CLOSE, 0);		/* here it always runs on midp main thread */	if (ts->sequences != NULL) {	    midpFree(ts->sequences);	    ts->sequences = NULL;	}	ts->singleTone = 0;	break;	    case SET_CUR_TIME:      {	int i, mtime=0;	ts->gain = 100;	for (i = 0; i < ts->seqlen; i += 2) {	  if (param <= mtime)	    break;	  if (ts->sequences[i] != INSEQ_SET_VOLUME){	    mtime += ts->sequences[i+1] >> 3;	  } else {	    ts->gain = (char)(ts->sequences[i+1] & 0x7f);	  }	}	ts->curNote = i-2;	ts->sampleLeft = 0;		ts->curMTime = mtime;	ret = mtime;      }      break;	    case GET_CUR_TIME:	ret = ts->curMTime;	break;	    }        KNI_ReturnInt((jint)ret);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -