static SNDFILE* open_sample(SF_INFO* sfinfo, const char* name, int raw_samplerate, int raw_channels, int sndfile_format) { SNDFILE* sfp = NULL; bool raw = (raw_samplerate || raw_channels || sndfile_format); sfinfo->frames = 0; sfinfo->samplerate = 0; sfinfo->channels = 0; sfinfo->format = 0; sfinfo->sections = 0; sfinfo->seekable = 0; if (raw) { #if DEBUG id_name* idnames = names_sample_raw_format_get(); char* fmt_name = 0; int i; for (i = 0; idnames[i].name != 0; ++i) if (idnames[i].id == sndfile_format) fmt_name = idnames[i].name; sfinfo->samplerate = raw_samplerate; sfinfo->channels = raw_channels; sfinfo->format = sndfile_format; debug("Reading raw sample %s as %d %s %s\n", name, raw_samplerate, (raw_channels == 2)? "stereo" : "mono", fmt_name); #endif if (!sf_format_check(sfinfo)) { pf_error(PF_ERR_SAMPLE_SNDFILE_FORMAT); return 0; } } else { debug("Reading sample %s\n", name); } if ((sfp = sf_open(name, SFM_READ, sfinfo)) == NULL) { pf_error(PF_ERR_SAMPLE_SNDFILE_OPEN); return 0; } return sfp; }
static int update_value (Param_Type *pf) { char buf[PF_MAX_LINE_LEN]; char *b; if ((pf->flags & PF_CURRENT_VALUE) == 0) return 0; if (pf->flags & PF_INDIRECT_VALUE) return 0; if (pf->type & PF_LIST_TYPE) return 0; b = buf; switch (pf->type & 0xFF) { case PF_INTEGER_TYPE: sprintf (buf, "%d", pf->current_value.ival); break; case PF_UINT_TYPE: sprintf (buf, "%u", pf->current_value.uval); break; case PF_REAL_TYPE: case PF_DOUBLE_TYPE: sprintf (buf, "%.16g", pf->current_value.dval); break; case PF_FILE_TYPE: case PF_STRING_TYPE: b = pf->current_value.sval; if (strlen (b) >= PF_MAX_LINE_LEN) { pf_error ("String value is too long for parameter file."); PF_Errno = PF_BAD_ARGUMENT; return -1; } break; case PF_BOOLEAN_TYPE: strcpy (buf, (pf->current_value.ival ? "yes" : "no")); break; default: pf_error ("update_value: Type %c is not supported", pf->type & 0xFF); PF_Errno = PF_NOT_IMPLEMENTED; return -1; } if (pf->value != NULL) SLFREE (pf->value); if (NULL == (pf->value = _pf_create_string (b))) return -1; return 0; }
/* If the object in the location pointed to by sval is non-NULL, it will be * freed. */ static int parse_string_according_to_type (char *str, unsigned int type, int *ival, double *dval, char **sval) { switch (type) { case PF_UINT_TYPE: case PF_INTEGER_TYPE: return _pf_parse_single_number (str, ival, NULL); case PF_BOOLEAN_TYPE: return _pf_parse_boolean (str, ival); case PF_REAL_TYPE: case PF_DOUBLE_TYPE: return _pf_parse_single_number (str, NULL, dval); case PF_STRING_TYPE: case PF_FILE_TYPE: /* This is easy */ if (*sval != NULL) SLFREE (*sval); if (NULL == (*sval = _pf_create_string (str))) return -1; return 0; default: pf_error ("type %d not implemented.", type); PF_Errno = PF_NOT_IMPLEMENTED; } return -1; }
/* Modes are: q-query, a-auto, h-hidden, l-learn */ int _pf_parse_mode (char *str, unsigned int *modep) { unsigned int mode = 0; /* There should be no spaces but we will allow it. */ str = _pf_skip_whitespace (str); if (*str == 0) { pf_error ("Mode information is missing."); PF_Errno = PF_CORRUPT_FIELD; return -1; } while (*str) { switch (*str) { default: pf_error ("Unrecognized mode (%c).", *str); PF_Errno = PF_CORRUPT_FIELD; return -1; case 'q': mode |= PF_QUERY_MODE; break; case 'a': mode |= PF_AUTO_MODE; break; case 'h': mode |= PF_HIDDEN_MODE; break; case 'l': mode |= PF_LEARN_MODE; break; } str++; /* There should be no spaces but we will allow it. */ str = _pf_skip_whitespace (str); } *modep = mode; return 0; }
static float* resample(float* samples, int rate, SF_INFO* sfinfo) { double ratio; int err; SRC_DATA src; float* tmp; ratio = rate / (sfinfo->samplerate * 1.0); debug("Resampling from %d to %d\n", rate, sfinfo->samplerate); src.src_ratio = ratio; src.data_in = samples; src.input_frames = sfinfo->frames; src.output_frames = sfinfo->frames * ratio; if (src.output_frames >= MAX_SAMPLE_FRAMES) { pf_error(PF_ERR_SAMPLE_RESAMPLE_MAX_FRAMES); return 0; } tmp = malloc(sizeof(float) * sfinfo->frames * sfinfo->channels * ratio); if (!tmp) { pf_error(PF_ERR_SAMPLE_RESAMPLE_ALLOC); return 0; } src.data_out = tmp; err = src_simple(&src, SRC_SINC_BEST_QUALITY, sfinfo->channels); if (err) { pf_error(PF_ERR_SAMPLE_SRC_SIMPLE); free(tmp); return 0; } sfinfo->frames = src.output_frames; return tmp; }
static float* read_audio(SNDFILE* sfp, SF_INFO* sfinfo) { float* tmp; if (sfinfo->frames >= MAX_SAMPLE_FRAMES) { pf_error(PF_ERR_SAMPLE_MAX_FRAMES); return 0; } if (sfinfo->channels > 2) { pf_error(PF_ERR_SAMPLE_CHANNEL_COUNT); sf_close (sfp); return 0; } /* set aside space for samples */ if (!(tmp = malloc(sfinfo->frames * sfinfo->channels * sizeof(*tmp)))) { pf_error(PF_ERR_SAMPLE_ALLOC); sf_close (sfp); return 0; } /* load sample file into memory */ if (sf_readf_float(sfp, tmp, sfinfo->frames) != sfinfo->frames) { pf_error(PF_ERR_SAMPLE_SNDFILE_READ); free(tmp); return 0; } debug("Read %d frames into memory.\n", (int) sfinfo->frames); return tmp; }
Param_File_Type *_pf_read_parm_file (char *file, FILE *fp) { Param_File_Type *parm_file; Param_Type *pf, *last_pf; unsigned int line_num; char buf[PF_MAX_LINE_LEN]; if (NULL == (parm_file = create_param_file_type (file))) { return NULL; } line_num = 0; last_pf = NULL; while (NULL != fgets (buf, sizeof(buf), fp)) { unsigned int len; char *line; line_num++; line = _pf_skip_whitespace (buf); if (*line == 0) continue; /* Now knock off final newline */ len = strlen (line) - 1; /* strlen (line) is > 0 */ if (line[len] == '\n') line[len] = 0; if (NULL == (pf = create_param_type (line))) { _pf_free_param_file (parm_file); pf_error ("Error on line %d of %s", line_num, file); return NULL; } pf->pfile = parm_file; if (last_pf == NULL) { parm_file->pf = pf; } else last_pf->next = pf; last_pf = pf; } return parm_file; }
int sample_default(Sample* sample, int rate) { int frames = rate / 8; float* tmp; LFO* lfo; LFOParams lfopar; int i; double v; float const* lfo_out; debug("Creating default sample\n"); if (!(tmp = malloc(frames * 2 * sizeof(*tmp)))) { pf_error(PF_ERR_SAMPLE_DEFAULT_ALLOC); return -1; } sample->frames = frames; sample->sp = tmp; lfo = lfo_new(); lfo_init(lfo); lfo_params_init(&lfopar, 523.251, LFO_SHAPE_SAW); lfo_trigger(lfo, &lfopar); lfo_out = lfo_output(lfo); for (i = 0; i < frames; ++i) { lfo_tick(lfo); v = *lfo_out * 0.9; *tmp++ = v; *tmp++ = v; } lfo_free(lfo); sample->filename = strdup("Default"); sample->default_sample = true; return 0; }
int sample_deep_copy(Sample* dest, const Sample* src) { size_t bytes = sizeof(float) * src->frames * 2 /* channels */; sample_shallow_copy(dest, src); dest->sp = malloc(bytes); if (!dest->sp) { pf_error(PF_ERR_SAMPLE_ALLOC_COPY); return -1; } memcpy(dest->sp, src->sp, bytes); return 0; }
static float* mono_to_stereo(float* samples, SF_INFO* sfinfo) { debug("Converting mono to stereo...\n"); int i; float* tmp = malloc(sizeof(float) * sfinfo->frames * 2); if (!tmp) { pf_error(PF_ERR_SAMPLE_CHANNEL_ALLOC); return 0; } for (i = 0; i < sfinfo->frames; i++) tmp[2 * i] = tmp[2 * i + 1] = samples[i]; return tmp; }
Sample* sample_new(void) { Sample* sample = malloc(sizeof(*sample)); if (!sample) { pf_error(PF_ERR_SAMPLE_ALLOC); return 0; } sample->sp = 0; sample->frames = 0; sample->filename = 0; sample->raw_samplerate = 0; sample->raw_channels = 0; sample->sndfile_format = 0; sample->default_sample = false; return sample; }
static Param_Type *get_object (Param_File_Type *p, char *name, unsigned int type, unsigned int mode) { Param_Type *pf; if (p == NULL) return NULL; if (NULL == (pf = _pf_locate_param_by_type (p, name, type))) { pf_error ("%s:\nError locating parameter named '%s' of type '%c'", p->input_filename, name, map_type_to_char (type)); return NULL; } if (-1 == _pf_get_value (p, pf, mode)) return NULL; return pf; }
static int do_indirect_shell_cmd (char *cmd, char **val) { FILE *fp; char buf[4 * PF_MAX_LINE_LEN]; char *b; unsigned int len; if (NULL == (fp = popen (cmd, "r"))) { PF_Errno = PF_INDIRECT_ERROR; pf_error ("Unable to execute shell command %s", cmd); return -1; } len = fread (buf, 1, sizeof (buf)-1, fp); buf [len] = 0; (void) pclose (fp); /* Remove trailing new line characters */ while (len && (buf[len-1] == '\n')) { len--; buf [len] = 0; } b = buf; while (*b != 0) { if (*b == '\n') *b = ' '; b++; } if (NULL == (*val = _pf_create_string (buf))) return -1; return 0; }
int _pf_get_value (Param_File_Type *p, Param_Type *pf, unsigned int ormode) { int perform_query; unsigned int mode; if (pf->type == PF_COMMENT_TYPE) return 0; mode = _pf_get_effective_mode (p, pf); perform_query = ((0 == (pf->flags & PF_CURRENT_VALUE)) && (mode & PF_QUERY_MODE)); mode |= ormode; if (perform_query == 0) perform_query = ormode & PF_QUERY_MODE; /* explicit requested */ if (-1 == _pf_get_current_value (p, pf)) { if ((PF_Errno != PF_NUMBER_FORMAT_BAD) && (PF_Errno != PF_INDIRECT_ERROR)) return -1; /* reset error and force a query */ pf_error ("Error occured while examining %s from %s.", pf->name, p->input_filename); PF_Errno = 0; perform_query = 1; } if (pf->flags & PF_CURRENT_VALUE) { if (-1 == range_check (p, pf)) { pf_error ("Range error occured while looking at parameter %s.", pf->name); if (PF_Errno != PF_RANGE_ERROR) return -1; /* Force query. */ perform_query = 1; } } else perform_query = 1; while (perform_query) { if (-1 == _pf_query_current_value (p, pf)) return -1; if (0 == range_check (p, pf)) break; if (PF_Errno != PF_RANGE_ERROR) return -1; pf_error ("Value is out of range."); } if ((mode & PF_LEARN_MODE) && (pf->flags & PF_PARAM_DIRTY)) { p->flags |= PFILE_DIRTY; if (-1 == update_value (pf)) return -1; } return 0; }
/* This routine strips a string s of surrounding quotes (if present). It * performs no backslash processing. * * Note: There is a weakness in the definition of fields that refer to other * parameters (indirect types). The weakness is that there appears to be no * way to form a string that starts with the two characters ')*' and not have * it interpreted as an indirect type. The weakness is in the definition as * expressed in the man pages for parameter files and NOT in my implementation. */ static char *parse_string_field (char *s, char **val, char *field) { char quote; char ch; quote = *s; if ((quote == '\'') || (quote == '"')) { /* Skip past quote */ s++; *val = s; } else { quote = ','; *val = s; } while (((ch = *s) != 0) && (ch != quote)) { if (ch == '\\') { s++; if (*s == 0) { pf_error ("Extra \\ character in %s field.", field); PF_Errno = PF_CORRUPT_FIELD; return NULL; } } s++; } if (quote == ',') { if (s == *val) *val = NULL; else *s = 0; if (ch != 0) s++; return s; } if (ch == 0) { pf_error ("Unable to find closing quote for %s field.", field); PF_Errno = PF_CORRUPT_FIELD; return NULL; } *s = 0; s++; /* skip quote. */ /* skip over whitespace too. Error if we do not see end of field */ s = _pf_skip_whitespace (s); if (*s != 0) { if (*s != ',') { pf_error ("Excess garbage at end of %s field.", field); PF_Errno = PF_CORRUPT_FIELD; return NULL; } s++; /* skip , */ } return s; }
static int get_indirect_object (Param_File_Type *p, char *name, char **val, int what) { char *file, *parm; Param_File_Type *new_p; Param_Type *pf; int ret; char *value; int is_file_indirect; if (*name != ')') { PF_Errno = PF_INDIRECT_ERROR; return -1; } name++; /* ))Shell Command */ if (*name == ')') return do_indirect_shell_cmd (name + 1, val); /* Note: The CXC parameter file library appears to support an indirection * of the form ")FILE.PARM", which means to use the value of PARM from FILE. * (note added Oct-30-2001) */ is_file_indirect = 0; if (*name == '*') { is_file_indirect = 1; name++; } if (NULL != _pf_strchr (name, '.')) /* HACK!!! Undocumented CXC parmeter file behavior. */ is_file_indirect = 1; if (is_file_indirect) { if (NULL == (parm = _pf_strchr (name, '.'))) { pf_error ("Indirection does not point to a parameter."); PF_Errno = PF_CORRUPT_FIELD; return -1; } file = _pf_create_nstring (name, (unsigned int) (parm - name)); if (file == NULL) return -1; parm++; /* skip . */ new_p = p = pf_open_parameter_file (file, "r"); if (p == NULL) { pf_error ("Unable to open indirect file %s.", file); SLFREE (file); PF_Errno = PF_INDIRECT_ERROR; return -1; } SLFREE (file); name = parm; } else new_p = NULL; if (NULL == (pf = _pf_locate_param_by_type (p, name, 0))) { if (new_p != NULL) pf_close_parameter_file (new_p); pf_error ("Bad indirect: %s", name); PF_Errno = PF_INDIRECT_ERROR; return -1; } ret = 0; if (what == 0) value = pf->value; else if (what == 1) value = pf->min; else value = pf->max; if (pf->flags & PF_DOING_INDIRECT) { pf_error ("Indirection loop found."); PF_Errno = PF_INDIRECT_ERROR; ret = -1; } else if (value == NULL) *val = NULL; else if (*value == ')') { pf->flags |= PF_DOING_INDIRECT; ret = get_indirect_object (p, value, val, what); pf->flags &= ~PF_DOING_INDIRECT; } else { if (NULL == (*val = _pf_create_string (value))) ret = -1; } if (new_p != NULL) pf_close_parameter_file (new_p); return ret; }
static int chop_line (char *line, char **name, char **type, char **mode, char **value, char **min, char **max, char **prompt) { char *s, ch; *name = line; *type = *mode = *min = *max = *value = *prompt = NULL; if (*line == '#') return 0; s = line; /* Find type */ while (((ch = *s) != 0) && (ch != ',')) s++; if (ch == 0) { pf_error ("%s\nUnable to find TYPE information.", line); PF_Errno = PF_CORRUPT_FIELD; return -1; } *s++ = 0; *type = s; /* Find mode */ while (((ch = *s) != 0) && (ch != ',')) s++; if (ch == 0) { pf_error ("%s\nUnable to find MODE information.", line); PF_Errno = PF_CORRUPT_FIELD; return -1; } *s++ = 0; *mode = s; while (((ch = *s) != 0) && (ch != ',')) s++; if (ch == 0) return 0; /* no more parameters */ *s++ = 0; /* terminate mode */ /* Rest of the fields are optional. We must be careful here because of * the possibilty of quote characters and embedded commas. */ /* Value field is next. */ s = parse_string_field (s, value, "VALUE"); if (s == NULL) return -1; s = parse_string_field (s, min, "MIN"); if (s == NULL) return -1; s = parse_string_field (s, max, "MAX"); if (s == NULL) return -1; s = parse_string_field (s, prompt, "PROMPT"); if (s == NULL) return -1; if (*s != 0) { pf_error ("Extra junk after prompt field for parameter '%s'", *name); return -1; } return 0; }
static Param_Type *create_param_type (char *line) { Param_Type *p; char *name, *type, *mode, *min, *max, *value, *prompt; p = (Param_Type *) _pf_malloc (sizeof (Param_Type)); if (p == NULL) return NULL; if (NULL == (p->name = _pf_create_string (line))) { goto free_and_return_error; } /* p->name is special. See comment in pf.h */ if (-1 == chop_line (line, &name, &type, &mode, &value, &min, &max, &prompt)) { goto free_and_return_error; } p->name[strlen (name)] = 0; if (type == NULL) { p->type = PF_COMMENT_TYPE; return p; } if (-1 == parse_type (type, &p->type)) { goto free_and_return_error; } if (-1 == _pf_parse_mode (mode, &p->mode)) { goto free_and_return_error; } if (min != NULL) { if (NULL == (p->min = _pf_unescape_string (min))) goto free_and_return_error; } if (max != NULL) { if (NULL == (p->max = _pf_unescape_string (max))) goto free_and_return_error; } if (value != NULL) { if (NULL == (p->value = _pf_unescape_string (value))) goto free_and_return_error; /* This is a weakness in the definition of parameter files. There * seems to be NO WAY to have a parameter whose value begins with * a ')' character. Actually, I think there is but the existing * practice seems to defeat my solution. */ if (*p->value == ')') p->flags |= PF_INDIRECT_VALUE; } if (prompt != NULL) { if (NULL == (p->prompt = _pf_unescape_string (prompt))) goto free_and_return_error; } return p; free_and_return_error: if ((p != NULL) && (p->name != NULL)) { pf_error ("Error processing parameter/line %s", p->name); } free_param_type (p); return NULL; }
/* The type can be b (bool), i (int), r (real), s (string), or f (file). * If the first character of type is a *, then it is a list. * The f-type has subtypes: e exists, n not-exists, r readable, w-writable */ static int parse_type (char *str, unsigned int *typep) { unsigned int type = 0; /* There should be no spaces but we will allow it. */ str = _pf_skip_whitespace (str); if (*str == 0) { pf_error ("Type information is missing."); PF_Errno = PF_CORRUPT_FIELD; return -1; } if (*str == '*') { type = PF_LIST_TYPE; str++; } if (0 == strcmp (str, "pset")) { /* FIXME!!! * What is this? It seems that SAO parameter files allow the type * field to be "pset". It appears to be the name of another * parameter file but their software treats it as a string. * * It appears that a parameter of type pset will make the * parameters of the referenced file available to this parameter file. * That is, it acts like an 'include' mechanism: * * foo,pset,h,xxx,,,etc ==> include xxx.par * foo,pset,h,,,etc ==> include foo.par */ str = "s"; } switch (*str) { default: pf_error ("Field has unrecognized type. (%c)", *str); PF_Errno = PF_CORRUPT_FIELD; return -1; case 'b': type |= PF_BOOLEAN_TYPE; str++; break; case 'i': type |= PF_INTEGER_TYPE; str++; break; case 'r': type |= PF_REAL_TYPE; str++; break; case 'd': type |= PF_DOUBLE_TYPE; str++; break; case 's': type |= PF_STRING_TYPE; str++; break; case 'f': type |= PF_FILE_TYPE; str++; while (*str) { switch (*str) { default: pf_error ("Unrecogized subtype '%c' for 'f' type.", *str); PF_Errno = PF_CORRUPT_FIELD; return -1; case 'e': if (type & PF_FILE_NEXISTS) { pf_error ("Error in file type: both n and e specified."); PF_Errno = PF_CORRUPT_FIELD; return -1; } type |= PF_FILE_EXISTS; break; case 'n': if (type & PF_FILE_EXISTS) { pf_error ("Error in file type: both n and e specified."); PF_Errno = PF_CORRUPT_FIELD; return -1; } type |= PF_FILE_NEXISTS; break; case 'r': type |= PF_FILE_READABLE; break; case 'w': type |= PF_FILE_WRITABLE; break; } str++; } break; } str = _pf_skip_whitespace (str); if (*str != 0) { pf_error ("Garbage at end of parameter type: '%s'", str); PF_Errno = PF_CORRUPT_FIELD; return -1; } *typep = type; return 0; }
static int range_check (Param_File_Type *p, Param_Type *pf) { char *min, *max; int imin, imax; double dmin, dmax; unsigned int type; if ((pf->flags & PF_CURRENT_VALUE) == 0) { pf_error ("Unable to check range of missing value for %s.", pf->name); PF_Errno = PF_BAD_ARGUMENT; return -1; } min = pf->min; max = pf->max; type = pf->type & 0xFF; if ((min != NULL) && (*min == ')')) if (-1 == get_indirect_min (p, pf->min, &min)) return -1; if ((max != NULL) && (*max == ')')) if (-1 == get_indirect_max (p, pf->max, &max)) return -1; if ((min == NULL) && (max == NULL)) return 0; if ((min != NULL) && (_pf_strchr (min, '|') || (type == PF_STRING_TYPE))) return enumerated_value_check (pf, min); if ((max != NULL) && (_pf_strchr (max, '|') || (type == PF_STRING_TYPE))) return enumerated_value_check (pf, max); switch (type) { case PF_INTEGER_TYPE: if (min != NULL) { if (-1 == _pf_parse_single_number (min, &imin, NULL)) return -1; if (pf->current_value.ival < imin) break; } if (max != NULL) { if (-1 == _pf_parse_single_number (max, &imax, NULL)) return -1; if (pf->current_value.ival > imax) break; } return 0; case PF_UINT_TYPE: if (min != NULL) { if (-1 == _pf_parse_single_number (min, &imin, NULL)) return -1; if (pf->current_value.uval < (unsigned int) imin) break; } if (max != NULL) { if (-1 == _pf_parse_single_number (max, &imax, NULL)) return -1; if (pf->current_value.uval > (unsigned int) imax) break; } return 0; case PF_DOUBLE_TYPE: case PF_REAL_TYPE: if (min != NULL) { if (-1 == _pf_parse_single_number (min, NULL, &dmin)) return -1; if (pf->current_value.dval < dmin) break; } if (max != NULL) { if (-1 == _pf_parse_single_number (max, NULL, &dmax)) return -1; if (pf->current_value.dval > dmax) break; } return 0; case PF_FILE_TYPE: /* The file type should also check whether or not the other * file conditions are met instead of this silly test below. */ case PF_STRING_TYPE: if ((min != NULL) && (strcmp (min, pf->current_value.sval) > 0)) break; if ((max != NULL) && (strcmp (max, pf->current_value.sval) < 0)) break; return 0; default: return 0; } PF_Errno = PF_RANGE_ERROR; return -1; }
int acissim_init (Param_File_Type *p) { char *dir; char dirbuf [1024]; if (-1 == pf_get_parameters (p, Acis_Parm_Table)) { pf_error ("acissim_init: error getting parameters."); return -1; } dir = Henke_Dir; if (*dir == '$') { char *env_end; char *env = dir + 1; env_end = strchr (env, '/'); if (env_end != NULL) { unsigned int env_len = env_end - env; strncpy (dirbuf, env, env_len); dirbuf [env_len] = 0; env = dirbuf; } fprintf (stdout, "Setting HENKE data directory from %s environment variable\n", env); dir = getenv (env); if (dir == NULL) { fprintf (stderr, "Environment variable %s needs set\n", env); return -1; } if (env_end != NULL) { sprintf (dirbuf, "%s%s", dir, env_end); dir = dirbuf; } } fprintf (stdout, "Setting Henke Directory to %s.\n", dir); if (-1 == henke_set_data_dir (dir)) { fprintf (stderr, "Unable to set Henke Directory.\n"); return -1; } if (-1 == setup_filter ()) return -1; Diffusion_Constant = Diffusion_Constant * 1.0e8; /* from cm^2 to um^2 */ Dopant_Concentration = Dopant_Concentration * 1.0e-12; /* to 1/um^3 */ Depletion_Boundary = Dead_Thickness + Depletion_Thickness; Field_Free_Boundary = Depletion_Boundary + Field_Free_Thickness; Substrate_Boundary = Field_Free_Boundary + Substrate_Thickness; Total_Thickness = Substrate_Boundary; Spread_Function = epi_spread; Fluor_Absorbtion_Coeff = absorbtion_coeff (Fluor_Emission_Energy); return 0; }