/************************************************************** * write audio data to buffer ***************************************************************/ void audiowrite(void) { int cbuff = 0, count, numwr, trgt; char *tmpptr; /* Uncatch the signals, so we don't clean up twice */ signal(SIGINT, SIG_DFL); /* Child process writes the audio */ while(1) { /* Wait for dirty buffer */ down(sndsemid, cbuff); /* Spit to the audio device */ if(buffinf[cbuff].setit) { snd_parm(buffinf[cbuff].speed, buffinf[cbuff].bits, buffinf[cbuff].stereo); buffinf[cbuff].setit = 0; } trgt = buffinf[cbuff].count; numwr = 0; tmpptr = buffarr[cbuff]; while ( (numwr < trgt) && ((count = write(audio, tmpptr, trgt - numwr)) > 0)) { if (count == -1) ErrDie("write"); numwr += count; tmpptr += count; } #ifdef DEBUG fprintf(stderr, "out:%d, %d\n", cbuff, numwr); #endif /* Was it the last buffer? */ if (buffinf[cbuff].last) { up(disksemid, cbuff); /* Not really needed */ break; } /* Mark as clean */ up(disksemid, cbuff); /* Update counter */ cbuff++; cbuff %= numbuffs; } /* Tidy up and be reaped */ sleep(10000); sync_audio(); close(audio); exit(0); }
static int sync_node(PNode *n) { PNode *target; int sync = 1; if((target = nodedb_lookup(n->id)) == NULL) { LOG_WARN(("Couldn't look up existing (target) node for %u--aborting sync", n->id)); return 0; } /* First sync node-head data, such as name and tags. */ sync &= sync_head(n, target); switch(n->type) { case V_NT_OBJECT: sync &= sync_object((NodeObject *) n, (NodeObject *) target); break; case V_NT_GEOMETRY: sync &= sync_geometry((NodeGeometry *) n, (NodeGeometry *) target); break; case V_NT_MATERIAL: sync &= sync_material((NodeMaterial *) n, (NodeMaterial *) target); break; case V_NT_BITMAP: sync &= sync_bitmap((NodeBitmap *) n, (NodeBitmap *) target); break; case V_NT_TEXT: sync &= sync_text((NodeText *) n, (NodeText *) target); break; case V_NT_CURVE: sync &= sync_curve((NodeCurve *) n, (NodeCurve *) target); break; case V_NT_AUDIO: sync &= sync_audio((NodeAudio *) n, (NodeAudio *) target); break; default: printf("Can't sync node of type %d\n", n->type); } return sync; }
int audio_thread(void *param) { SND_EVENT evnt; int buffsize; int samples; int err; char *errstr; int active; if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0) { errstr = "Cannot create sound buffer\n\r"; goto exit_whith_error; }; SetVolume(hBuff,-900,-900); if((err = GetBufferSize(hBuff, &buffsize)) != 0) { errstr = "Cannot get buffer size\n\r"; goto exit_whith_error; }; __sync_or_and_fetch(&threads_running,AUDIO_THREAD); resampler_size = buffsize = buffsize/2; samples = buffsize/4; while( player_state != CLOSED) { uint32_t offset; double event_stamp, wait_stamp; int too_late = 0; switch(sound_state) { case PREPARE: mutex_lock(&astream.lock); if(astream.count < buffsize*2) { memset(astream.buffer+astream.count, 0, buffsize*2-astream.count); astream.count = buffsize*2; }; SetBuffer(hBuff, astream.buffer, 0, buffsize*2); astream.count -= buffsize*2; if(astream.count) memcpy(astream.buffer, astream.buffer+buffsize*2, astream.count); mutex_unlock(&astream.lock); SetTimeBase(hBuff, audio_base); case PAUSE_2_PLAY: GetTimeStamp(hBuff, &last_time_stamp); // printf("last audio time stamp %f\n", last_time_stamp); if((err = PlayBuffer(hBuff, 0)) !=0 ) { errstr = "Cannot play buffer\n\r"; goto exit_whith_error; }; active = 1; sync_audio(hBuff, buffsize); sound_state = PLAY; // printf("render: set audio latency to %f\n", audio_delta); /* breaktrough */ case PLAY: GetNotify(&evnt); if(evnt.code != 0xFF000001) { printf("invalid event code %d\n\r", evnt.code); continue; } if(evnt.stream != hBuff) { printf("invalid stream %x hBuff= %x\n\r", evnt.stream, hBuff); continue; }; offset = evnt.offset; mutex_lock(&astream.lock); if(astream.count < buffsize) { memset(astream.buffer+astream.count, 0, buffsize-astream.count); astream.count = buffsize; }; SetBuffer(hBuff, astream.buffer, offset, buffsize); { double val = 0; int16_t *src = (int16_t*)astream.buffer; int samples = buffsize/2; int i; for(i = 0, val = 0; i < samples/2; i++, src++) if(val < abs(*src)) val= abs(*src); // * *src; sound_level_0 = val; //sqrt(val / (samples/2)); for(i = 0, val = 0; i < samples/2; i++, src++) if(val < abs(*src)) val= abs(*src); // * *src; sound_level_1 = val; //sqrt(val / (samples/2)); // printf("%d\n", sound_level); }; samples_written+= buffsize/4; astream.count -= buffsize; if(astream.count) memcpy(astream.buffer, astream.buffer+buffsize, astream.count); mutex_unlock(&astream.lock); break; case PLAY_2_STOP: if( active ) { ResetBuffer(hBuff, SND_RESET_ALL); audio_base = -1.0; active = 0; } sound_state = STOP; break; case PLAY_2_PAUSE: if( active ) { StopBuffer(hBuff); }; sound_state = PAUSE; case PAUSE: case STOP: delay(1); }; } __sync_and_and_fetch(&threads_running,~AUDIO_THREAD); StopBuffer(hBuff); DestroyBuffer(hBuff); return 0; exit_whith_error: printf(errstr); return -1; };