Beispiel #1
0
// install installs the library, package, or binary associated with dir,
// which is relative to $GOROOT/src.
static void
install(char *dir)
{
	char *name, *p, *elem, *prefix, *exe;
	bool islib, ispkg, isgo, stale, ispackcmd;
	Buf b, b1, path;
	Vec compile, files, link, go, missing, clean, lib, extra;
	Time ttarg, t;
	int i, j, k, n, doclean, targ;

	if(vflag) {
		if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
			errprintf("%s (%s/%s)\n", dir, goos, goarch);
		else
			errprintf("%s\n", dir);
	}

	binit(&b);
	binit(&b1);
	binit(&path);
	vinit(&compile);
	vinit(&files);
	vinit(&link);
	vinit(&go);
	vinit(&missing);
	vinit(&clean);
	vinit(&lib);
	vinit(&extra);


	// path = full path to dir.
	bpathf(&path, "%s/src/%s", goroot, dir);
	name = lastelem(dir);

	// For misc/prof, copy into the tool directory and we're done.
	if(hasprefix(dir, "misc/")) {
		copy(bpathf(&b, "%s/%s", tooldir, name),
			bpathf(&b1, "%s/misc/%s", goroot, name), 1);
		goto out;
	}

	// For release, cmd/prof is not included.
	if((streq(dir, "cmd/prof")) && !isdir(bstr(&path))) {
		if(vflag > 1)
			errprintf("skipping %s - does not exist\n", dir);
		goto out;
	}

	// set up gcc command line on first run.
	if(gccargs.len == 0) {
		bprintf(&b, "%s %s", defaultcc, defaultcflags);
		splitfields(&gccargs, bstr(&b));
		for(i=0; i<nelem(proto_gccargs); i++)
			vadd(&gccargs, proto_gccargs[i]);
		if(defaultcflags[0] == '\0') {
			for(i=0; i<nelem(proto_gccargs2); i++)
				vadd(&gccargs, proto_gccargs2[i]);
		}
		if(contains(gccargs.p[0], "clang")) {
			// disable ASCII art in clang errors, if possible
			vadd(&gccargs, "-fno-caret-diagnostics");
			// clang is too smart about unused command-line arguments
			vadd(&gccargs, "-Qunused-arguments");
		}
		// disable word wrapping in error messages
		vadd(&gccargs, "-fmessage-length=0");
		if(streq(gohostos, "darwin")) {
			// golang.org/issue/5261
			vadd(&gccargs, "-mmacosx-version-min=10.6");
		}
	}
	if(ldargs.len == 0 && defaultldflags[0] != '\0') {
		bprintf(&b, "%s", defaultldflags);
		splitfields(&ldargs, bstr(&b));
	}

	islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
	ispkg = hasprefix(dir, "pkg");
	isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");

	exe = "";
	if(streq(gohostos, "windows"))
		exe = ".exe";

	// Start final link command line.
	// Note: code below knows that link.p[targ] is the target.
	ispackcmd = 0;
	if(islib) {
		// C library.
		vadd(&link, "ar");
		if(streq(gohostos, "plan9"))
			vadd(&link, "rc");
		else
			vadd(&link, "rsc");
		prefix = "";
		if(!hasprefix(name, "lib"))
			prefix = "lib";
		targ = link.len;
		vadd(&link, bpathf(&b, "%s/pkg/obj/%s_%s/%s%s.a", goroot, gohostos, gohostarch, prefix, name));
	} else if(ispkg) {
		// Go library (package).
		ispackcmd = 1;
		vadd(&link, "pack"); // program name - unused here, but all the other cases record one
		p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir+4);
		*xstrrchr(p, '/') = '\0';
		xmkdirall(p);
		targ = link.len;
		vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir+4));
	} else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) {
		// Go command.
		vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar));
		vadd(&link, "-o");
		elem = name;
		if(streq(elem, "go"))
			elem = "go_bootstrap";
		targ = link.len;
		vadd(&link, bpathf(&b, "%s/%s%s", tooldir, elem, exe));
	} else {
		// C command. Use gccargs and ldargs.
		if(streq(gohostos, "plan9")) {
			vadd(&link, bprintf(&b, "%sl", gohostchar));
			vadd(&link, "-o");
			targ = link.len;
			vadd(&link, bpathf(&b, "%s/%s", tooldir, name));
		} else {
			vcopy(&link, gccargs.p, gccargs.len);
			vcopy(&link, ldargs.p, ldargs.len);
			if(sflag)
				vadd(&link, "-static");
			vadd(&link, "-o");
			targ = link.len;
			vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
			if(streq(gohostarch, "amd64"))
				vadd(&link, "-m64");
			else if(streq(gohostarch, "386"))
				vadd(&link, "-m32");
		}
	}
	ttarg = mtime(link.p[targ]);

	// Gather files that are sources for this target.
	// Everything in that directory, and any target-specific
	// additions.
	xreaddir(&files, bstr(&path));

	// Remove files beginning with . or _,
	// which are likely to be editor temporary files.
	// This is the same heuristic build.ScanDir uses.
	// There do exist real C files beginning with _,
	// so limit that check to just Go files.
	n = 0;
	for(i=0; i<files.len; i++) {
		p = files.p[i];
		if(hasprefix(p, ".") || (hasprefix(p, "_") && hassuffix(p, ".go")))
			xfree(p);
		else
			files.p[n++] = p;
	}
	files.len = n;

	for(i=0; i<nelem(deptab); i++) {
		if(streq(dir, deptab[i].prefix) ||
		   (hassuffix(deptab[i].prefix, "/") && hasprefix(dir, deptab[i].prefix))) {
			for(j=0; (p=deptab[i].dep[j])!=nil; j++) {
				breset(&b1);
				bwritestr(&b1, p);
				bsubst(&b1, "$GOROOT", goroot);
				bsubst(&b1, "$GOOS", goos);
				bsubst(&b1, "$GOARCH", goarch);
				p = bstr(&b1);
				if(hassuffix(p, ".a")) {
					vadd(&lib, bpathf(&b, "%s", p));
					continue;
				}
				if(hassuffix(p, "/*")) {
					bpathf(&b, "%s/%s", bstr(&path), p);
					b.len -= 2;
					xreaddir(&extra, bstr(&b));
					bprintf(&b, "%s", p);
					b.len -= 2;
					for(k=0; k<extra.len; k++)
						vadd(&files, bpathf(&b1, "%s/%s", bstr(&b), extra.p[k]));
					continue;
				}
				if(hasprefix(p, "-")) {
					p++;
					n = 0;
					for(k=0; k<files.len; k++) {
						if(hasprefix(files.p[k], p))
							xfree(files.p[k]);
						else
							files.p[n++] = files.p[k];
					}
					files.len = n;
					continue;
				}
				vadd(&files, p);
			}
		}
	}
	vuniq(&files);

	// Convert to absolute paths.
	for(i=0; i<files.len; i++) {
		if(!isabs(files.p[i])) {
			bpathf(&b, "%s/%s", bstr(&path), files.p[i]);
			xfree(files.p[i]);
			files.p[i] = btake(&b);
		}
	}

	// Is the target up-to-date?
	stale = rebuildall;
	n = 0;
	for(i=0; i<files.len; i++) {
		p = files.p[i];
		for(j=0; j<nelem(depsuffix); j++)
			if(hassuffix(p, depsuffix[j]))
				goto ok;
		xfree(files.p[i]);
		continue;
	ok:
		t = mtime(p);
		if(t != 0 && !hassuffix(p, ".a") && !shouldbuild(p, dir)) {
			xfree(files.p[i]);
			continue;
		}
		if(hassuffix(p, ".go"))
			vadd(&go, p);
		if(t > ttarg)
			stale = 1;
		if(t == 0) {
			vadd(&missing, p);
			files.p[n++] = files.p[i];
			continue;
		}
		files.p[n++] = files.p[i];
	}
	files.len = n;

	// If there are no files to compile, we're done.
	if(files.len == 0)
		goto out;
	
	for(i=0; i<lib.len && !stale; i++)
		if(mtime(lib.p[i]) > ttarg)
			stale = 1;

	if(!stale)
		goto out;

	// For package runtime, copy some files into the work space.
	if(streq(dir, "pkg/runtime")) {
		copy(bpathf(&b, "%s/arch_GOARCH.h", workdir),
			bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
		copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
			bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
		p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
		if(isfile(p))
			copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
		copy(bpathf(&b, "%s/os_GOOS.h", workdir),
			bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
		copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
			bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
	}

	// Generate any missing files; regenerate existing ones.
	for(i=0; i<files.len; i++) {
		p = files.p[i];
		elem = lastelem(p);
		for(j=0; j<nelem(gentab); j++) {
			if(gentab[j].gen == nil)
				continue;
			if(hasprefix(elem, gentab[j].nameprefix)) {
				if(vflag > 1)
					errprintf("generate %s\n", p);
				gentab[j].gen(bstr(&path), p);
				// Do not add generated file to clean list.
				// In pkg/runtime, we want to be able to
				// build the package with the go tool,
				// and it assumes these generated files already
				// exist (it does not know how to build them).
				// The 'clean' command can remove
				// the generated files.
				goto built;
			}
		}
		// Did not rebuild p.
		if(find(p, missing.p, missing.len) >= 0)
			fatal("missing file %s", p);
	built:;
	}

	// One more copy for package runtime.
	// The last batch was required for the generators.
	// This one is generated.
	if(streq(dir, "pkg/runtime")) {
		copy(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
			bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
	}

	// Generate .c files from .goc files.
	if(streq(dir, "pkg/runtime")) {
		for(i=0; i<files.len; i++) {
			p = files.p[i];
			if(!hassuffix(p, ".goc"))
				continue;
			// b = path/zp but with _goos_goarch.c instead of .goc
			bprintf(&b, "%s%sz%s", bstr(&path), slash, lastelem(p));
			b.len -= 4;
			bwritef(&b, "_%s_%s.c", goos, goarch);
			goc2c(p, bstr(&b));
			vadd(&files, bstr(&b));
		}
		vuniq(&files);
	}

	if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
		// We've generated the right files; the go command can do the build.
		if(vflag > 1)
			errprintf("skip build for cross-compile %s\n", dir);
		goto nobuild;
	}

	// Compile the files.
	for(i=0; i<files.len; i++) {
		if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
			continue;
		name = lastelem(files.p[i]);

		vreset(&compile);
		if(!isgo) {
			// C library or tool.
			if(streq(gohostos, "plan9")) {
				vadd(&compile, bprintf(&b, "%sc", gohostchar));
				vadd(&compile, "-FTVwp");
				vadd(&compile, "-DPLAN9");
				vadd(&compile, "-D__STDC__=1");
				vadd(&compile, "-D__SIZE_TYPE__=ulong"); // for GNU Bison
				vadd(&compile, bpathf(&b, "-I%s/include/plan9", goroot));
				vadd(&compile, bpathf(&b, "-I%s/include/plan9/%s", goroot, gohostarch));
			} else {
				vcopy(&compile, gccargs.p, gccargs.len);
				vadd(&compile, "-c");
				if(streq(gohostarch, "amd64"))
					vadd(&compile, "-m64");
				else if(streq(gohostarch, "386"))
					vadd(&compile, "-m32");
	
				vadd(&compile, "-I");
				vadd(&compile, bpathf(&b, "%s/include", goroot));
			}

			if(streq(dir, "lib9"))
				vadd(&compile, "-DPLAN9PORT");


			vadd(&compile, "-I");
			vadd(&compile, bstr(&path));

			// lib9/goos.c gets the default constants hard-coded.
			if(streq(name, "goos.c")) {
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOARCH=\"%s\"", goarch));
				bprintf(&b1, "%s", goroot_final);
				bsubst(&b1, "\\", "\\\\");  // turn into C string
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOROOT=\"%s\"", bstr(&b1)));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOVERSION=\"%s\"", goversion));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GO_EXTLINK_ENABLED=\"%s\"", goextlinkenabled));
			}

			// gc/lex.c records the GOEXPERIMENT setting used during the build.
			if(streq(name, "lex.c")) {
				xgetenv(&b, "GOEXPERIMENT");
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b1, "GOEXPERIMENT=\"%s\"", bstr(&b)));
			}
		} else {
			// Supporting files for a Go package.
			if(hassuffix(files.p[i], ".s"))
				vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar));
			else {
				vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar));
				vadd(&compile, "-F");
				vadd(&compile, "-V");
				vadd(&compile, "-w");
			}
			vadd(&compile, "-I");
			vadd(&compile, workdir);
			vadd(&compile, "-I");
			vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
			vadd(&compile, "-D");
			vadd(&compile, bprintf(&b, "GOOS_%s", goos));
			vadd(&compile, "-D");
			vadd(&compile, bprintf(&b, "GOARCH_%s", goarch));
			vadd(&compile, "-D");
			vadd(&compile, bprintf(&b, "GOOS_GOARCH_%s_%s", goos, goarch));
		}

		bpathf(&b, "%s/%s", workdir, lastelem(files.p[i]));
		doclean = 1;
		if(!isgo && streq(gohostos, "darwin")) {
			// To debug C programs on OS X, it is not enough to say -ggdb
			// on the command line.  You have to leave the object files
			// lying around too.  Leave them in pkg/obj/, which does not
			// get removed when this tool exits.
			bpathf(&b1, "%s/pkg/obj/%s", goroot, dir);
			xmkdirall(bstr(&b1));
			bpathf(&b, "%s/%s", bstr(&b1), lastelem(files.p[i]));
			doclean = 0;
		}

		// Change the last character of the output file (which was c or s).
		if(streq(gohostos, "plan9"))
			b.p[b.len-1] = gohostchar[0];
		else
			b.p[b.len-1] = 'o';
		vadd(&compile, "-o");
		vadd(&compile, bstr(&b));
		vadd(&compile, files.p[i]);
		bgrunv(bstr(&path), CheckExit, &compile);

		vadd(&link, bstr(&b));
		if(doclean)
			vadd(&clean, bstr(&b));
	}
	bgwait();

	if(isgo) {
		// The last loop was compiling individual files.
		// Hand the Go files to the compiler en masse.
		vreset(&compile);
		vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));

		bpathf(&b, "%s/_go_.a", workdir);
		vadd(&compile, "-pack");
		vadd(&compile, "-o");
		vadd(&compile, bstr(&b));
		vadd(&clean, bstr(&b));
		if(!ispackcmd)
			vadd(&link, bstr(&b));

		vadd(&compile, "-p");
		if(hasprefix(dir, "pkg/"))
			vadd(&compile, dir+4);
		else
			vadd(&compile, "main");

		if(streq(dir, "pkg/runtime"))
			vadd(&compile, "-+");

		vcopy(&compile, go.p, go.len);

		runv(nil, bstr(&path), CheckExit, &compile);

		if(ispackcmd) {
			xremove(link.p[targ]);
			dopack(link.p[targ], bstr(&b), &link.p[targ+1], link.len - (targ+1));
			goto nobuild;
		}
	}

	if(!islib && !isgo) {
		// C binaries need the libraries explicitly, and -lm.
		vcopy(&link, lib.p, lib.len);
		if(!streq(gohostos, "plan9"))
			vadd(&link, "-lm");
	}

	// Remove target before writing it.
	xremove(link.p[targ]);

	runv(nil, nil, CheckExit, &link);

nobuild:
	// In package runtime, we install runtime.h and cgocall.h too,
	// for use by cgo compilation.
	if(streq(dir, "pkg/runtime")) {
		copy(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
			bpathf(&b1, "%s/src/pkg/runtime/cgocall.h", goroot), 0);
		copy(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
			bpathf(&b1, "%s/src/pkg/runtime/runtime.h", goroot), 0);
	}


out:
	for(i=0; i<clean.len; i++)
		xremove(clean.p[i]);

	bfree(&b);
	bfree(&b1);
	bfree(&path);
	vfree(&compile);
	vfree(&files);
	vfree(&link);
	vfree(&go);
	vfree(&missing);
	vfree(&clean);
	vfree(&lib);
	vfree(&extra);
}
Beispiel #2
0
void iLBC_encode( 
    unsigned char *bytes,           /* (o) encoded data bits iLBC */ 
    float *block,                   /* (o) speech vector to encode */ 
    iLBC_Enc_Inst_t *iLBCenc_inst   /* (i/o) the general encoder  
                                           state */ 
){ 
     
    float data[BLOCKL]; 
    float residual[BLOCKL], reverseResidual[BLOCKL]; 
 
    int start, idxForMax, idxVec[STATE_LEN]; 
    float reverseDecresidual[BLOCKL], mem[CB_MEML]; 
    int n, k, meml_gotten, Nfor, Nback, i, pos; 
    int gain_index[CB_NSTAGES*NASUB], extra_gain_index[CB_NSTAGES]; 
    int cb_index[CB_NSTAGES*NASUB],extra_cb_index[CB_NSTAGES]; 
    int lsf_i[LSF_NSPLIT*LPC_N]; 
    unsigned char *pbytes; 
    int diff, start_pos, state_first; 
    float en1, en2; 
    int index, ulp, firstpart; 
    int subcount, subframe; 
    float weightState[LPC_FILTERORDER]; 
    float syntdenum[NSUB*(LPC_FILTERORDER+1)];  
    float weightdenum[NSUB*(LPC_FILTERORDER+1)];  
    float decresidual[BLOCKL]; 
 
    /* high pass filtering of input signal if such is not done  
           prior to calling this function */ 
 
    /*hpInput(block, BLOCKL, data, (*iLBCenc_inst).hpimem);*/ 
 
    /* otherwise simply copy */ 
 
    memcpy(data,block,BLOCKL*sizeof(float)); 
         
    /* LPC of hp filtered input data */ 
 
    LPCencode(syntdenum, weightdenum, lsf_i, data, 
        iLBCenc_inst); 
 
    /* inverse filter to get residual */ 
 
    for (n=0; n<NSUB; n++ ) { 
        anaFilter(&data[n*SUBL], &syntdenum[n*(LPC_FILTERORDER+1)],  
            SUBL, &residual[n*SUBL], (*iLBCenc_inst).anaMem); 
    } 
 
    /* find state location */ 
 
    start = FrameClassify(residual); 
     
    /* check if state should be in first or last part of the  
    two subframes */ 
 
    diff = STATE_LEN - STATE_SHORT_LEN; 
    en1 = 0; 
    index = (start-1)*SUBL; 
    for (i = 0; i < STATE_SHORT_LEN; i++) { 
        en1 += residual[index+i]*residual[index+i]; 
    } 
    en2 = 0; 
    index = (start-1)*SUBL+diff; 
    for (i = 0; i < STATE_SHORT_LEN; i++) { 
        en2 += residual[index+i]*residual[index+i]; 
    } 
     
     
    if (en1 > en2) { 
        state_first = 1; 
        start_pos = (start-1)*SUBL; 
    } else { 
        state_first = 0; 
        start_pos = (start-1)*SUBL + diff; 
    } 
 
    /* scalar quantization of state */ 
 
    StateSearchW(&residual[start_pos],  
        &syntdenum[(start-1)*(LPC_FILTERORDER+1)],  
        &weightdenum[(start-1)*(LPC_FILTERORDER+1)], &idxForMax,  
        idxVec, STATE_SHORT_LEN, state_first); 
 
    StateConstructW(idxForMax, idxVec,  
        &syntdenum[(start-1)*(LPC_FILTERORDER+1)],  
        &decresidual[start_pos], STATE_SHORT_LEN); 
 
    /* predictive quantization in state */ 
     
    if (state_first) { /* put adaptive part in the end */ 
         
        /* setup memory */ 
 
        memset(mem, 0, (CB_MEML-STATE_SHORT_LEN)*sizeof(float)); 
        memcpy(mem+CB_MEML-STATE_SHORT_LEN, decresidual+start_pos,  
                       STATE_SHORT_LEN*sizeof(float)); 
        memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); 
 
        /* encode subframes */ 
 
        iCBSearch(extra_cb_index, extra_gain_index,  
            &residual[start_pos+STATE_SHORT_LEN],  
            mem+CB_MEML-stMemLTbl, 
            stMemLTbl, diff, CB_NSTAGES,  
            &weightdenum[start*(LPC_FILTERORDER+1)], weightState, 0); 
 
        /* construct decoded vector */ 
 
        iCBConstruct(&decresidual[start_pos+STATE_SHORT_LEN], 
            extra_cb_index, extra_gain_index, mem+CB_MEML-stMemLTbl,  
            stMemLTbl, diff, CB_NSTAGES); 
     
    }  
    else { /* put adaptive part in the beginning */ 
         
        /* create reversed vectors for prediction */ 
 
        for(k=0; k<diff; k++ ){ 
            reverseResidual[k] = residual[(start+1)*SUBL -1 
                -(k+STATE_SHORT_LEN)]; 
        } 
         
        /* setup memory */ 
 
        meml_gotten = STATE_SHORT_LEN; 
        for( k=0; k<meml_gotten; k++){  
            mem[CB_MEML-1-k] = decresidual[start_pos + k]; 
        }  
        memset(mem, 0, (CB_MEML-k)*sizeof(float)); 
        memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); 
         
        /* encode subframes */ 
 
        iCBSearch(extra_cb_index, extra_gain_index,  
            reverseResidual, mem+CB_MEML-stMemLTbl, stMemLTbl, diff,  
            CB_NSTAGES, &weightdenum[(start-1)*(LPC_FILTERORDER+1)],  
            weightState, 0); 
 
        /* construct decoded vector */ 
 
        iCBConstruct(reverseDecresidual, extra_cb_index,  
            extra_gain_index, mem+CB_MEML-stMemLTbl, stMemLTbl, diff,  
            CB_NSTAGES); 
         
        /* get decoded residual from reversed vector */ 
 
        for( k=0; k<diff; k++ ){ 
            decresidual[start_pos-1-k] = reverseDecresidual[k]; 
        } 
    } 
 
    /* counter for predicted subframes */ 
 
    subcount=0; 
 
    /* forward prediction of subframes */ 
 
    Nfor = NSUB-start-1; 
 
     
    if( Nfor > 0 ){ 
         
        /* setup memory */ 
 
        memset(mem, 0, (CB_MEML-STATE_LEN)*sizeof(float)); 
        memcpy(mem+CB_MEML-STATE_LEN, decresidual+(start-1)*SUBL,  
            STATE_LEN*sizeof(float)); 
        memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); 
 
        /* loop over subframes to encode */ 
 
        for (subframe=0; subframe<Nfor; subframe++) { 
 
            /* encode subframe */ 
 
            iCBSearch(cb_index+subcount*CB_NSTAGES,  
                gain_index+subcount*CB_NSTAGES,  
                &residual[(start+1+subframe)*SUBL],  
                mem+CB_MEML-memLfTbl[subcount], memLfTbl[subcount],  
                SUBL, CB_NSTAGES,  
                &weightdenum[(start+1+subframe)*(LPC_FILTERORDER+1)], 
                weightState, subcount+1); 
 
            /* construct decoded vector */ 
 
            iCBConstruct(&decresidual[(start+1+subframe)*SUBL],  
                cb_index+subcount*CB_NSTAGES,  
                gain_index+subcount*CB_NSTAGES,  
                mem+CB_MEML-memLfTbl[subcount], memLfTbl[subcount],  
                SUBL, CB_NSTAGES); 
 
            /* update memory */ 
 
            memcpy(mem, mem+SUBL, (CB_MEML-SUBL)*sizeof(float)); 
            memcpy(mem+CB_MEML-SUBL,  
                &decresidual[(start+1+subframe)*SUBL],  
                SUBL*sizeof(float)); 
            memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); 
 
            subcount++; 
        } 
    } 
     
 
    /* backward prediction of subframes */ 
 
    Nback = start-1; 
 
     
    if( Nback > 0 ){ 
                
        /* create reverse order vectors */ 
 
        for( n=0; n<Nback; n++ ){ 
            for( k=0; k<SUBL; k++ ){ 
                reverseResidual[n*SUBL+k] =  
                    residual[(start-1)*SUBL-1-n*SUBL-k]; 
                reverseDecresidual[n*SUBL+k] =  
                    decresidual[(start-1)*SUBL-1-n*SUBL-k]; 
            } 
        } 
 
        /* setup memory */ 
 
        meml_gotten = SUBL*(NSUB+1-start); 
 
         
        if( meml_gotten > CB_MEML ) {  
            meml_gotten=CB_MEML; 
        } 
        for( k=0; k<meml_gotten; k++) {  
            mem[CB_MEML-1-k] = decresidual[(start-1)*SUBL + k]; 
        }  
        memset(mem, 0, (CB_MEML-k)*sizeof(float)); 
        memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); 
 
        /* loop over subframes to encode */ 
 
        for (subframe=0; subframe<Nback; subframe++) { 
             
            /* encode subframe */ 
 
            iCBSearch(cb_index+subcount*CB_NSTAGES,  
                gain_index+subcount*CB_NSTAGES,  
                &reverseResidual[subframe*SUBL],  
                mem+CB_MEML-memLfTbl[subcount], memLfTbl[subcount],  
                SUBL, CB_NSTAGES,  
                &weightdenum[(start-2-subframe)*(LPC_FILTERORDER+1)],  
                weightState, subcount+1); 
 
            /* construct decoded vector */ 
 
            iCBConstruct(&reverseDecresidual[subframe*SUBL],  
                cb_index+subcount*CB_NSTAGES,  
                gain_index+subcount*CB_NSTAGES,  
                mem+CB_MEML-memLfTbl[subcount],  
                memLfTbl[subcount], SUBL, CB_NSTAGES); 
 
            /* update memory */ 
 
            memcpy(mem, mem+SUBL, (CB_MEML-SUBL)*sizeof(float)); 
            memcpy(mem+CB_MEML-SUBL,  
                &reverseDecresidual[subframe*SUBL], 
                SUBL*sizeof(float)); 
            memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); 
 
            subcount++; 
 
        } 
 
        /* get decoded residual from reversed vector */ 
 
        for (i = 0; i < SUBL*Nback; i++) { 
            decresidual[SUBL*Nback - i - 1] =  
                reverseDecresidual[i]; 
        } 
    } 
    /* end encoding part */ 
 
    /* adjust index */ 
    index_conv_enc(cb_index); 
 
    /* pack bytes */ 
 
    pbytes=bytes; 
    pos=0; 
 
    /* loop over the 3 ULP classes */ 
 
    for (ulp=0; ulp<3; ulp++) { 
     
        /* LSF */ 
        for (k=0;k<6;k++) { 
            packsplit(&lsf_i[k], &firstpart, &lsf_i[k],  
                ulp_lsf_bitsTbl[k][ulp],  
                ulp_lsf_bitsTbl[k][ulp]+ 
                ulp_lsf_bitsTbl[k][ulp+1]+ 
                ulp_lsf_bitsTbl[k][ulp+2]); 
            dopack( &pbytes, firstpart,  
                ulp_lsf_bitsTbl[k][ulp], &pos); 
        } 
 
        /* Start block info */ 
 
        packsplit(&start, &firstpart, &start,  
            ulp_start_bitsTbl[ulp],  
            ulp_start_bitsTbl[ulp]+ 
            ulp_start_bitsTbl[ulp+1]+ 
            ulp_start_bitsTbl[ulp+2]); 
        dopack( &pbytes, firstpart,  
            ulp_start_bitsTbl[ulp], &pos); 
 
        packsplit(&state_first, &firstpart, &state_first,  
            ulp_startfirst_bitsTbl[ulp],  
            ulp_startfirst_bitsTbl[ulp]+ 
            ulp_startfirst_bitsTbl[ulp+1]+ 
            ulp_startfirst_bitsTbl[ulp+2]); 
        dopack( &pbytes, firstpart,  
            ulp_startfirst_bitsTbl[ulp], &pos); 
 
        packsplit(&idxForMax, &firstpart, &idxForMax,  
            ulp_scale_bitsTbl[ulp], ulp_scale_bitsTbl[ulp]+ 
            ulp_scale_bitsTbl[ulp+1]+ulp_scale_bitsTbl[ulp+2]); 
        dopack( &pbytes, firstpart,  
            ulp_scale_bitsTbl[ulp], &pos); 
 
        for (k=0; k<STATE_SHORT_LEN; k++) { 
            packsplit(idxVec+k, &firstpart, idxVec+k,  
                ulp_state_bitsTbl[ulp],  
                ulp_state_bitsTbl[ulp]+ 
                ulp_state_bitsTbl[ulp+1]+ 
                ulp_state_bitsTbl[ulp+2]); 
            dopack( &pbytes, firstpart,  
                ulp_state_bitsTbl[ulp], &pos); 
        } 
 
        /* 22 sample block */ 
 
        for (k=0;k<CB_NSTAGES;k++) { 
            packsplit(extra_cb_index+k, &firstpart,  
                extra_cb_index+k,  
                ulp_extra_cb_indexTbl[k][ulp],  
                ulp_extra_cb_indexTbl[k][ulp]+ 
                ulp_extra_cb_indexTbl[k][ulp+1]+ 
                ulp_extra_cb_indexTbl[k][ulp+2]); 
            dopack( &pbytes, firstpart,  
                ulp_extra_cb_indexTbl[k][ulp], &pos); 
        } 
        for (k=0;k<CB_NSTAGES;k++) { 
            packsplit(extra_gain_index+k, &firstpart,  
                extra_gain_index+k,  
                ulp_extra_cb_gainTbl[k][ulp],  
                ulp_extra_cb_gainTbl[k][ulp]+ 
                ulp_extra_cb_gainTbl[k][ulp+1]+ 
                ulp_extra_cb_gainTbl[k][ulp+2]); 
            dopack( &pbytes, firstpart,  
                ulp_extra_cb_gainTbl[k][ulp], &pos); 
        } 
             
        /* The four 40 sample sub blocks */ 
 
        for (i=0; i<NASUB; i++) { 
            for (k=0; k<CB_NSTAGES; k++) { 
                packsplit(cb_index+i*CB_NSTAGES+k, &firstpart,  
                    cb_index+i*CB_NSTAGES+k,  
                    ulp_cb_indexTbl[i][k][ulp],  
                    ulp_cb_indexTbl[i][k][ulp]+ 
                    ulp_cb_indexTbl[i][k][ulp+1]+ 
                    ulp_cb_indexTbl[i][k][ulp+2]); 
                dopack( &pbytes, firstpart,  
                    ulp_cb_indexTbl[i][k][ulp], &pos); 
            } 
        } 
         
        for (i=0; i<NASUB; i++) { 
            for (k=0; k<CB_NSTAGES; k++) { 
                packsplit(gain_index+i*CB_NSTAGES+k, &firstpart,  
                    gain_index+i*CB_NSTAGES+k,  
                    ulp_cb_gainTbl[i][k][ulp],  
                    ulp_cb_gainTbl[i][k][ulp]+ 
                    ulp_cb_gainTbl[i][k][ulp+1]+ 
                    ulp_cb_gainTbl[i][k][ulp+2]); 
                dopack( &pbytes, firstpart,  
                    ulp_cb_gainTbl[i][k][ulp], &pos); 
            } 
        } 
    } 
 
    /* set the last unused bit to zero */ 
    dopack( &pbytes, 0, 1, &pos); 
}