Exemplo n.º 1
0
void Voice::Interpolate(sample_t* pSrc) {
    float effective_volume = 1;  // TODO: use the art. data instead
    int   i = 0;

    // ************************************************
    // TODO: ARTICULATION DATA HANDLING IS MISSING HERE
    // ************************************************

    // FIXME: assuming either mono or stereo
    if (this->pSample->Channels == 2) { // Stereo Sample
        while (i < this->OutputBufferSize) {
            #ifdef USE_LINEAR_INTERPOLATION
                int   pos_int   = double_to_int(this->Pos);  // integer position
                float pos_fract = this->Pos - pos_int;       // fractional part of position
                pos_int <<= 1;
                // left channel
                this->pOutput[i++] += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));
                // right channel
                this->pOutput[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));
            #else // polynomial interpolation
                //FIXME: !!!THIS WON'T WORK!!! needs to be adjusted for stereo, use linear interpolation meanwhile
                xm1 = pSrc[pos_int];
                x0  = pSrc[pos_int+1];
                x1  = pSrc[pos_int+2];
                x2  = pSrc[pos_int+3];
                a   = (3 * (x0-x1) - xm1 + x2) / 2;
                b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
                c   = (x1 - xm1) / 2;
                this->pOutput[u] += effective_volume*((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
            #endif // USE_LINEAR_INTERPOLATION

            this->Pos += this->CurrentPitch;
        }
    }
    else { // Mono Sample
        while (i < this->OutputBufferSize) {
            #ifdef USE_LINEAR_INTERPOLATION
                int   pos_int       = double_to_int(this->Pos);  // integer position
                float pos_fract     = this->Pos - pos_int;       // fractional part of position
                float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));
                this->pOutput[i]   += sample_point;
                this->pOutput[i+1] += sample_point;
                i += 2;
            #else // polynomial interpolation
                //FIXME: !!!THIS WON'T WORK!!! needs to be adjusted for stereo, use linear interpolation meanwhile
                xm1 = pSrc[pos_int];
                x0  = pSrc[pos_int+1];
                x1  = pSrc[pos_int+2];
                x2  = pSrc[pos_int+3];
                a   = (3 * (x0-x1) - xm1 + x2) / 2;
                b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
                c   = (x1 - xm1) / 2;
               this->pOutput[u] += effective_volume*((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
            #endif

            this->Pos += this->CurrentPitch;
        }
    }
}
Exemplo n.º 2
0
void Voice::RenderAudio() {

    switch (this->PlaybackState) {

        case playback_state_ram: {
                Interpolate((sample_t*) pSample->GetCache().pStart);
                if (DiskVoice) {
                    // check if we reached the allowed limit of the sample RAM cache
                    if (Pos > MaxRAMPos) {
                        dmsg(("Voice: switching to disk playback (Pos=%f)\n", Pos));
                        this->PlaybackState = playback_state_disk;
                    }
                }
                else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {
                    this->PlaybackState = playback_state_end;
                }
            }
            break;

        case playback_state_disk: {
                if (!DiskStreamRef.pStream) {
                    // check if the disk thread created our ordered disk stream in the meantime
                    DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
                    if (!DiskStreamRef.pStream) {
                        std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
                        pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
                        this->Active = false;
                        return;
                    }
                    DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (double_to_int(Pos) - MaxRAMPos));
                    Pos -= double_to_int(Pos);
                }

                // add silence sample at the end if we reached the end of the stream (for the interpolator)
                if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (OutputBufferSize << MAX_PITCH) / pSample->Channels) {
                    DiskStreamRef.pStream->WriteSilence((OutputBufferSize << MAX_PITCH) / pSample->Channels);
                    this->PlaybackState = playback_state_end;
                }

                sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
                Interpolate(ptr);
                DiskStreamRef.pStream->IncrementReadPos(double_to_int(Pos) * pSample->Channels);
                Pos -= double_to_int(Pos);
            }
            break;

        case playback_state_end:
            this->Active = false; // free voice
            break;
    }
}
Exemplo n.º 3
0
int __fixdfsi(double a)
{
	double_t da;
	
	da.val = a;
	return double_to_int(da.data);
}
Exemplo n.º 4
0
NODE *
format_val(char *format, int index, register NODE *s)
{
	char buf[BUFSIZ];
	register char *sp = buf;
	double val;
	char *orig, *trans, save;

	if (! do_traditional && (s->flags & INTLSTR) != 0) {
		save = s->stptr[s->stlen];
		s->stptr[s->stlen] = '\0';

		orig = s->stptr;
		trans = dgettext(TEXTDOMAIN, orig);

		s->stptr[s->stlen] = save;
		return tmp_string(trans, strlen(trans));
	}

	/* not an integral value, or out of range */
	if ((val = double_to_int(s->numbr)) != s->numbr
	    || val < LONG_MIN || val > LONG_MAX) {
		/*
		 * Once upon a time, if GFMT_WORKAROUND wasn't defined,
		 * we just blindly did this:
		 *	sprintf(sp, format, s->numbr);
		 *	s->stlen = strlen(sp);
		 *	s->stfmt = (char) index;
		 * but that's no good if, e.g., OFMT is %s. So we punt,
		 * and just always format the value ourselves.
		 */

		NODE *dummy, *r;
		unsigned short oflags;
		extern NODE **fmt_list;          /* declared in eval.c */

		/* create dummy node for a sole use of format_tree */
		getnode(dummy);
		dummy->type = Node_expression_list;
		dummy->lnode = s;
		dummy->rnode = NULL;
		oflags = s->flags;
		s->flags |= PERM; /* prevent from freeing by format_tree() */
		r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
		s->flags = oflags;
		s->stfmt = (char) index;
		s->stlen = r->stlen;
		s->stptr = r->stptr;
		freenode(r);		/* Do not free_temp(r)!  We want */
		freenode(dummy);	/* to keep s->stptr == r->stpr.  */

		goto no_malloc;
	} else {
		/* integral value */
	        /* force conversion to long only once */
		register long num = (long) val;
		if (num < NVAL && num >= 0) {
			sp = (char *) values[num];
			s->stlen = 1;
		} else {
			(void) sprintf(sp, "%ld", num);
			s->stlen = strlen(sp);
		}
		s->stfmt = -1;
	}
	emalloc(s->stptr, char *, s->stlen + 2, "format_val");
	memcpy(s->stptr, sp, s->stlen+1);
no_malloc:
	s->stref = 1;
	s->flags |= STR;
	s->flags &= ~UNINITIALIZED;
	return s;
}