You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 2 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  5. <title>The Sound Library</title>
  6. <style type="text/css">
  7. EM.red {color:red; font-style:normal}
  8. EM.def {font-style:italic; font-weight: bold}
  9. H1 {text-align: center}
  10. UL {list-style-type: none}
  11. DIV.center {text-align: center}
  12. A {text-decoration:none}
  13. A:hover {text-decoration:underline}
  14. A.quiet {color:black; text-decoration:none}
  15. A.quiet:hover {text-decoration:underline}
  16. A.def {font-weight: bold; font-style: normal; text-decoration:none; text-color:black}
  17. DIV.topheader {margin-top: 10px;
  18. margin-bottom: 40px;
  19. border: 4px solid #00ff00; /* green */
  20. background-color: #f5f5dc; /* beige */
  21. font-family: 'Helvetica';
  22. font-size: 30px;
  23. text-align: center;
  24. padding-top: 10px;
  25. padding-bottom: 10px;
  26. }
  27. DIV.innerheader {margin-top: 60px;
  28. margin-bottom: 30px;
  29. border: 4px solid #00ff00; /* green */
  30. background-color: #eefdee; /* lightgreen */
  31. padding-left: 30px;
  32. width: 50%;
  33. padding-top: 20px;
  34. padding-bottom: 20px;
  35. }
  36. DIV.header {margin-top: 50px;
  37. margin-bottom: 10px;
  38. font-size: 20px;
  39. font-weight: bold;
  40. border: 4px solid #00ff00; /* green */
  41. background-color: #f5f5dc; /* beige */
  42. text-align: center;
  43. padding-top: 20px;
  44. padding-bottom: 20px;
  45. }
  46. DIV.related {text-align:center;
  47. border: 1px solid lightgray;
  48. margin-bottom: 1.0cm;
  49. margin-top: 1.0cm;
  50. padding-top: 10px;
  51. padding-bottom: 10px;
  52. background-color: #f0f0f0;
  53. }
  54. TD.green {background-color: lightgreen;
  55. padding-left: 1.0cm;}
  56. TD.beige {background-color: beige}
  57. BODY.body {background-color: #ffffff; /* white */
  58. margin-left: 0.5cm;
  59. }
  60. </style>
  61. </head>
  62. <body class="body">
  63. <div class="topheader">SndLib</div>
  64. <div class="center">Bill Schottstaedt (bil@ccrma.stanford.edu)</div>
  65. <div class="related">
  66. related documentation: &nbsp;
  67. <a href="snd.html">snd.html &nbsp;</a>
  68. <a href="grfsnd.html">grfsnd.html &nbsp;</a>
  69. <a href="extsnd.html">extsnd.html &nbsp;</a>
  70. <a href="sndscm.html">sndscm.html &nbsp;</a>
  71. <a href="sndclm.html">sndclm.html &nbsp;</a>
  72. <a href="s7.html">s7.html &nbsp;</a>
  73. <a href="index.html">index.html</a>
  74. </div>
  75. <div class="header">Contents</div>
  76. <ul>
  77. <li><a href="#introduction">Introduction</a>
  78. <li><a href="#headers">Headers</a>
  79. <li><a href="#data">Data</a>
  80. <li><a href="#hardware">Hardware</a>
  81. <li><a href="#music5">Music V</a>
  82. <li><a href="#examples">Examples</a>
  83. <ul>
  84. <li><a href="#sndinfo">SndInfo</a>
  85. <li><a href="#sndplay">SndPlay</a>
  86. <li><a href="#sndsine">SndSine</a>
  87. <li><a href="#clmosc">clmosc</a>
  88. <li><a href="#otherexamples">Other Examples</a>
  89. </ul>
  90. <li><a href="#sndlibxen">Extension Languages</a>
  91. </ul>
  92. <div class="header" id="introduction">Introduction</div>
  93. <p>sndlib is a collection of sound file and sound synthesis
  94. function written in C and running currently in various Unices
  95. via OSS or ALSA, Mac OSX, and on old Windows systems.
  96. To build sndlib (sndlib.so if possible, and sndlib.a):
  97. </p>
  98. <pre>
  99. ./configure
  100. make
  101. </pre>
  102. <p>To install it, 'make install' &mdash; I've tested this process in Linux.
  103. </p>
  104. <p>The following files make up sndlib:</p>
  105. <ul>
  106. <li>io.c (read and write sound file data)
  107. <li>headers.c (read and write sound file headers)
  108. <li>audio.c (read and write sound hardware ports)
  109. <li>sound.c (provide slightly higher level access to the preceding files)
  110. <li>sndlib.h (header for the preceding files)
  111. <li>sndlib2xen.c and sndlib-strings.h (tie preceding into s7, Ruby, or Forth)
  112. <li>clm.c and clm.h (Music V implementation)
  113. <li>clm2xen.c, vct.c and vct.h (tie clm.c into s7, Ruby, or Forth)
  114. <li>xen.h, xen.c (the embedded language support)
  115. </ul>
  116. <p>
  117. The naming scheme is more as less as follows:
  118. the sndlib prefix is "mus" so
  119. function names start with "mus_" and constants start with "MUS_".
  120. Functions involving sound files referenced through the file name
  121. start with "mus_sound_", functions involving files at a lower level
  122. with "mus_file_", functions involving header access with "mus_header_",
  123. functions involving audio hardware access with "mus_audio_",
  124. and various
  125. others just with "mus_" (number translations, etc). Conversions use
  126. the word "to" as in "mus_samples_to_bytes".
  127. </p>
  128. <div class="header" id="headers">Headers</div>
  129. <p>Sound files have built-in descriptors known as headers.
  130. The following functions return the information in the header.
  131. In each case the argument to the function is the full file
  132. name of the sound file.
  133. </p>
  134. <pre>
  135. mus_long_t mus_sound_samples (const char *arg) /* samples of sound according to header */
  136. mus_long_t mus_sound_framples (const char *arg) /* samples per channel */
  137. float mus_sound_duration (const char *arg) /* sound duration in seconds */
  138. mus_long_t mus_sound_length (const char *arg) /* true file length in bytes */
  139. int mus_sound_datum_size (const char *arg) /* bytes per sample */
  140. mus_long_t mus_sound_data_location (const char *arg) /* location of first sample (bytes) */
  141. int mus_sound_bits_per_sample(const char *arg) /* bits per sample */
  142. int mus_bytes_per_sample(int format) /* bytes per sample */
  143. int mus_sound_chans (const char *arg) /* number of channels (samples are interleaved) */
  144. int mus_sound_srate (const char *arg) /* sampling rate */
  145. mus_header_t mus_sound_header_type (const char *arg) /* header type (aiff etc) */
  146. mus_sample_t mus_sound_sample_type (const char *arg) /* sample type (alaw etc) */
  147. int mus_sound_original_format (const char *arg) /* unmodified sample type specifier */
  148. int mus_sound_type_specifier (const char *arg) /* original header type identifier */
  149. char *mus_sound_comment (const char *arg) /* comment if any */
  150. mus_long_t mus_sound_comment_start (const char *arg) /* comment start (bytes) if any */
  151. mus_long_t mus_sound_comment_end (const char *arg) /* comment end (bytes) */
  152. int *mus_sound_loop_info(const char *arg) /* 8 loop vals (mode,start,end) then base-detune and base-note (empty list if no loop info found) */
  153. int mus_sound_write_date (const char *arg) /* bare (uninterpreted) file write date */
  154. int mus_sound_initialize(void) /* initialize everything */
  155. </pre>
  156. <p>The following can be used to provide user-understandable descriptions
  157. of the header type and the sample type:</p>
  158. <pre>
  159. char *mus_header_type_name(mus_header_t type) /* "AIFF" etc */
  160. char *mus_sample_type_name(mus_sample_t samp_type) /* "16-bit big endian linear" etc */
  161. char *mus_header_type_to_string(mus_header_t type)
  162. char *mus_sample_type_to_string(mus_sample_t samp_type)
  163. const char *mus_sample_type_short_name(mus_sample_t samp_type)
  164. </pre>
  165. <p>In all cases if an error occurs, -1 (MUS_ERROR) is returned, and some sort of error message
  166. is printed; to customize error handling, use mus_set_error_handler and mus_set_print_handler.
  167. </p>
  168. <pre>
  169. mus_error_handler_t *mus_error_set_handler(mus_error_handler_t *new_error_handler);
  170. mus_print_handler_t *mus_print_set_handler(mus_print_handler_t *new_print_handler);
  171. </pre>
  172. <p>To decode the error indication, use:</p>
  173. <pre>
  174. char *mus_error_to_string(int err);
  175. </pre>
  176. <p>Header data is cached internally, so the actual header is read
  177. only if it hasn't already been read, or the write date has changed.
  178. Loop points are also available, if there's interest. To go below the
  179. "sound" level, see headers.c &mdash; once a header has been read, all the
  180. components that have been found can be read via functions such as
  181. <b>mus_header_srate</b>.
  182. </p>
  183. <div class="header" id="data">Data</div>
  184. <p>The following functions provide access to
  185. sound file data:</p>
  186. <pre>
  187. int mus_sound_open_input (const char *arg)
  188. int mus_sound_open_output (const char *arg, int srate, int chans, mus_sample_t sample_type, mus_header_t header_type, const char *comment)
  189. int mus_sound_reopen_output (const char *arg, mus_header_t type, mus_sample_t format, mus_long_t data_loc)
  190. int mus_sound_close_input (int fd)
  191. int mus_sound_close_output (int fd, mus_long_t bytes_of_data)
  192. int mus_sound_read (int fd, int beg, int end, int chans, mus_float_t **bufs)
  193. int mus_sound_write (int fd, int beg, int end, int chans, mus_float_t **bufs)
  194. mus_long_t mus_sound_seek_frample (int fd, mus_long_t frample)
  195. </pre>
  196. <p>mus_float_t defaults to double. It is set when
  197. sndlib is built, and refers to Sndlib's internal representation of sample values.
  198. </p>
  199. <p>mus_sound_open_input opens arg for reading. Most standard
  200. uncompressed formats are readable. This function returns the associated
  201. file number, or -1 upon failure. </p>
  202. <p>mus_sound_close_input closes an open sound file. Its argument is
  203. the integer returned by mus_sound_open_input.</p>
  204. <p>mus_sound_open_output opens (creates) the file arg, setting its sampling rate
  205. to be srate, number of channels to chans, sample type
  206. to sample_type (see sndlib.h for these types: MUS_BSHORT,
  207. means 16-bit 2's complement big endian fractions),
  208. header type to header_type (AIFF for example; the available
  209. writable header types are MUS_AIFC (or AIFF), MUS_RIFF ('wave'), MUS_RF64,
  210. MUS_NEXT, MUS_NIST, MUS_CAFF, and MUS_IRCAM), and comment (if any) to
  211. comment. The header is not considered complete without
  212. an indication of the data size, but since this is rarely known
  213. in advance, it is supplied when the sound file is closed. mus_sound_open_output
  214. function returns the associated file number.</p>
  215. <p>mus_sound_close_output first updates the file's header to
  216. reflect the final data size bytes_of_data, then closes
  217. the file. The argument fd is the integer returned by
  218. mus_sound_open_output.</p>
  219. <p>mus_sound_read reads data from the file indicated by fd,
  220. placing data in the array obufs as mus_float_t values (floats normally).
  221. chans determines how many arrays of
  222. samples are in obufs, which is filled by mus_sound_read from its
  223. index beg to end with zero padding if necessary.
  224. </p>
  225. <p>mus_sound_write writes samples to the file indicated by fd,
  226. starting for each of chans channels in obufs at
  227. beg and ending at end.</p>
  228. <p>mus_sound_seek_frample moves the read or write position for the
  229. file indicated by fd to the desired frample.
  230. </p>
  231. <div class="header" id="hardware">Hardware</div>
  232. <p>The following functions provide access to audio harware. If an
  233. error occurs, they return -1 (MUS_ERROR). </p>
  234. <pre>
  235. int mus_audio_initialize(void)
  236. int mus_audio_open_output(int dev, int srate, int chans, mus_sample_t format, int size)
  237. int mus_audio_open_input(int dev, int srate, int chans, mus_sample_t format, int size)
  238. int mus_audio_write(int line, char *buf, int bytes)
  239. int mus_audio_close(int line)
  240. int mus_audio_read(int line, char *buf, int bytes)
  241. </pre>
  242. <p>mus_audio_initialize takes care of any necessary initialization.</p>
  243. <p>mus_audio_open_input opens an audio port to read sound data (i.e. a microphone, line in, etc).
  244. The input device is dev (see sndlib.h for details; when in doubt, use MUS_AUDIO_DEFAULT).
  245. The input sampling rate is srate or as close as we
  246. can get to it. The number of input channels (if available) is chans.
  247. The input sample type is format (when in doubt, use the macro MUS_AUDIO_COMPATIBLE_FORMAT).
  248. And the input buffer size (if settable at all) is size (bytes). This
  249. function returns an integer to distinguish its port from others that might be
  250. in use.
  251. </p>
  252. <p>mus_audio_open_output opens an audio port to write data (i.e. speakers, line out, etc).
  253. The output device is dev (see sndlib.h). Its sampling rate is srate, number
  254. of channels chans, sample type format, and buffer size size. This
  255. function returns the associated line number of the output port.</p>
  256. <p>mus_audio_close closes the port (input or output) associated with line.</p>
  257. <p>mus_audio_read reads sound data from line. The incoming 'bytes' bytes of data are placed
  258. in buf. If no error was returned from mus_audio_open_input, the data is in the format requested
  259. by that function with channels interleaved.</p>
  260. <p>mus_audio_write writes 'bytes' bytes of data in buf to the output
  261. port associated with line. This data is assumed to be in the format
  262. requested by mus_audio_open_output with channels interleaved.</p>
  263. <div class="header" id="music5">Music V</div>
  264. <p>clm.c and friends implement all the generators found in CLM, a
  265. music V implementation, and clm2xen.c ties these into the languages supported by the
  266. xen package (currently s7, Ruby, and Forth). The
  267. primary clm documentation (which describes both the Scheme and Common Lisp implementations)
  268. is clm.html found in clm-5.tar.gz or sndclm.html in snd-16.tar.gz alongside sndlib at ccrma-ftp.
  269. The simplest way to try these out is to load them into Snd; see extsnd.html,
  270. <a href="sndscm.html#exampdoc">examp.scm</a>, and <a href="sndscm.html#sndtestdoc">snd-test.scm</a> in snd-16.tar.gz for more details.
  271. The following briefly describes the C calls (see clm.h).
  272. </p>
  273. <p>clm.c implements a bunch of generators and sound IO handlers. Each generator
  274. has three associated functions, make-gen, gen, and gen_p; the first
  275. creates the generator (if needed), the second gets the next sample from
  276. the generator, and the last examines some pointer to determine if it is
  277. that kind of generator. In addition, there are a variety of generic
  278. functions that generators respond to: mus_free, for example, frees a
  279. generator, and mus_frequency returns its current frequency, if relevant.
  280. All generators are pointers to mus_any structs.
  281. </p>
  282. <ul>
  283. <li>oscil &mdash; generate a sine wave.
  284. <ul>
  285. <li>mus_any *mus_make_oscil (float freq, float phase)
  286. <li>float mus_oscil (mus_any *o, float fm, float pm)
  287. <li>int mus_oscil_p (mus_any *ptr)
  288. </ul>
  289. <pre>
  290. mus_any *osc;
  291. osc = mus_make_oscil(440.0, 0.0);
  292. if (mus_oscil_p(osc))
  293. fprintf(stderr, "%.3f, %.3f ", .1 * mus_oscil(osc, 0.0, 0.0), mus_frequency(osc));
  294. mus_free(osc);
  295. </pre>
  296. </ul>
  297. <p>The other generators are:</p>
  298. <ul>
  299. <li>sum_of_cosines: generate a pulse train made up of cosines
  300. <li>sum_of_sines: generate a sum of sines
  301. <li>delay: a delay line with optional interpolation
  302. <li>tap: read delay line
  303. <li>comb: comb filter
  304. <li>notch: notch filter
  305. <li>all_pass: all pass filter
  306. <li>table_lookup: interpolating table lookup
  307. <li>sawtooth_wave, triangle_wave, pulse_train, square_wave
  308. <li>rand: white noise (a step function)
  309. <li>rand-interp: interpolating noise
  310. <li>asymmetric_fm: a variety of FM
  311. <li>one_zero, two_zero, one_pole, two_pole: basic filters
  312. <li>formant: create a formant region (two poles, two zeros)
  313. <li>sine_summation: another way to create sine waves
  314. <li>filter, fir_filter, iir_filter: direct form filters of any order
  315. <li>wave_train: sequence of possibly overlapping waves
  316. <li>env: envelopes
  317. <li>polyshape, polywave: waveshaping
  318. <li>readin, file_to_sample, file_to_frample, in_any: file sample input
  319. <li>locsig, sample_to_file, frample_to_file, out_any: file sample output
  320. <li>src: sampling rate conversion
  321. <li>granulate: granular synthesis
  322. <li>convolve: convolution
  323. <li>phase-vocoder: phase vocoder
  324. <li>moving-average: moving window average
  325. <li>ssb-am: single side-bank amplitude modulation
  326. </ul>
  327. <p>Some useful functions provided by clm.c are: </p>
  328. <ul>
  329. <li>float mus_radians_to_hz(float rads): convert radians/sample to cycles/sec.
  330. <li>float mus_hz_to_radians(float hz): and the reverse.
  331. <li>float mus_degrees_to_radians(float deg): convert degrees to radians.
  332. <li>float mus_radians_to_degrees(float rads): and the reverse.
  333. <li>float mus_srate(void): current sampling rate
  334. <li>float mus_set_srate(float rate): set current sampling rate
  335. <li>float mus_ring_modulate(float sig1, float sig2): multiply sig1 by sig2
  336. <li>float mus_amplitude_modulate(float s1, float s2, float s3): AM
  337. <li>float mus_contrast_enhancement(float sig, float index)
  338. <li>float mus_dot_product(float *data1, float *data2, int size)
  339. <li>void mus_clear_array(float *arr, int size)
  340. <li>float mus_array_interp(float *wave, float phase, int size)
  341. <li>float mus_polynomial(float *coeffs, float x, int ncoeffs);
  342. <li>void mus_multiply_arrays(float *data, float *window, int len);
  343. <li>void mus_rectangular_to_polar(float *rl, float *im, int size);
  344. <li>void mus_spectrum(float *rdat, float *idat, float *window, int n, int type)
  345. <li>void mus_fft(float *rl, float *im, int n, int isign)
  346. <li>float *mus_make_fft_window(int size, int type, float beta)
  347. <li>void mus_convolution(float* rl1, float* rl2, int n, int ipow)
  348. <li>float *mus_partials_to_wave(float *partial_data, int partials, float *table, int table_size, int normalize)
  349. <li>float *mus_phase_partials_to_wave(float *partial_data, int partials, float *table, int table_size, int normalize)
  350. <li>float mus_samples_to_seconds(mus_long_t samps)
  351. <li>mus_long_t mus_seconds_to_samples(float secs)
  352. </ul>
  353. <p>and various others: see clm.h.</p>
  354. <p>The more useful generic functions are:</p>
  355. <ul>
  356. <li>int mus_free(mus_any *ptr)
  357. <li>char *mus_describe(mus_any *gen)
  358. <li>float mus_phase(mus_any *gen)
  359. <li>float mus_set_phase(mus_any *gen, float val)
  360. <li>float mus_set_frequency(mus_any *gen, float val)
  361. <li>float mus_frequency(mus_any *gen)
  362. <li>float mus_run(mus_any *gen, float arg1, float arg2)
  363. <li>int mus_length(mus_any *gen)
  364. <li>int mus_set_length(mus_any *gen, int len)
  365. <li>float *mus_data(mus_any *gen)
  366. <li>float *mus_set_data(mus_any *gen, float *data)
  367. <li>char *mus_name(mus_any *ptr)
  368. <li>float mus_scaler(mus_any *gen)
  369. <li>float mus_set_scaler(mus_any *gen, float val)
  370. <li>float mus_apply(mus_any *gen, ...)
  371. </ul>
  372. <p>Errors are reported
  373. through mus_error which can be redirected or muffled. See clm2xen.c for an example.
  374. </p>
  375. <div class="header" id="examples">Examples</div>
  376. <div class="innerheader" id="sndinfo">sndinfo</div>
  377. <p>This program prints out a description of a sound file (sndinfo.c).</p>
  378. <pre>
  379. int main(int argc, char *argv[])
  380. {
  381. int fd, chans, srate;
  382. mus_long_t samples;
  383. float length;
  384. time_t date;
  385. char *comment;
  386. char timestr[64];
  387. mus_sound_initialize(); /* initialize sndlib */
  388. fd = mus_file_open_read(argv[1]); /* see if it exists */
  389. if (fd != -1)
  390. {
  391. close(fd);
  392. date = mus_sound_write_date(argv[1]);
  393. srate = mus_sound_srate(argv[1]);
  394. chans = mus_sound_chans(argv[1]);
  395. samples = mus_sound_samples(argv[1]);
  396. comment = mus_sound_comment(argv[1]);
  397. length = (double)samples / (float)(chans * srate);
  398. strftime(timestr, 64, "%a %d-%b-%y %H:%M %Z", localtime(&amp;date));
  399. fprintf(stdout, "%s:\n srate: %d\n chans: %d\n length: %f\n",
  400. argv[1], srate, chans, length);
  401. fprintf(stdout, " header: %s\n sample type: %s\n written: %s\n comment: %s\n",
  402. mus_header_type_name(mus_sound_header_type(argv[1])),
  403. mus_sample_type_name(mus_sound_sample_type(argv[1])),
  404. timestr, comment);
  405. }
  406. else
  407. fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
  408. return(0);
  409. }
  410. </pre>
  411. <div class="innerheader" id="sndplay">sndplay</div>
  412. <p>This code plays a sound file (sndplay.c):</p>
  413. <pre>
  414. int main(int argc, char *argv[])
  415. {
  416. int fd, afd, i, j, n, k, chans, srate, outbytes;
  417. mus_long_t framples;
  418. mus_float_t **bufs;
  419. short *obuf;
  420. mus_sound_initialize();
  421. fd = mus_sound_open_input(argv[1]);
  422. if (fd != -1)
  423. {
  424. chans = mus_sound_chans(argv[1]);
  425. srate = mus_sound_srate(argv[1]);
  426. framples = mus_sound_framples(argv[1]);
  427. outbytes = BUFFER_SIZE * chans * 2;
  428. bufs = (mus_float_t **)calloc(chans, sizeof(mus_float_t *));
  429. for (i=0;i&lt;chans;i++)
  430. bufs[i] = (mus_float_t *)calloc(BUFFER_SIZE, sizeof(mus_float_t));
  431. obuf = (short *)calloc(BUFFER_SIZE * chans, sizeof(short));
  432. afd = mus_audio_open_output(MUS_AUDIO_DEFAULT, srate, chans, MUS_AUDIO_COMPATIBLE_FORMAT, outbytes);
  433. if (afd != -1)
  434. {
  435. for (i = 0; i &lt; framples; i += BUFFER_SIZE)
  436. {
  437. mus_sound_read(fd, 0, BUFFER_SIZE - 1, chans, bufs);
  438. for (k = 0, j = 0; k &lt; BUFFER_SIZE; k++, j += chans)
  439. for (n = 0; n &lt; chans; n++)
  440. obuf[j + n] = MUS_SAMPLE_TO_SHORT(bufs[n][k]);
  441. mus_audio_write(afd, (char *)obuf, outbytes);
  442. }
  443. mus_audio_close(afd);
  444. }
  445. mus_sound_close_input(fd);
  446. for (i = 0; i &lt; chans; i++) free(bufs[i]);
  447. free(bufs);
  448. free(obuf);
  449. }
  450. return(0);
  451. }
  452. </pre>
  453. <div class="innerheader" id="sndsine">sndsine</div>
  454. <p>This program writes a one channel NeXT/Sun sound file
  455. containing a sine wave at 440 Hz.</p>
  456. <pre>
  457. int main(int argc, char *argv[])
  458. {
  459. int fd, i, k, framples;
  460. float phase, incr;
  461. mus_float_t *obuf[1];
  462. mus_sound_initialize();
  463. fd = mus_sound_open_output(argv[1], 22050, 1, MUS_BSHORT, MUS_NEXT, "created by sndsine");
  464. if (fd != -1)
  465. {
  466. framples = 22050;
  467. phase = 0.0;
  468. incr = 2 * M_PI * 440.0 / 22050.0;
  469. obuf[0] = (mus_float_t *)calloc(BUFFER_SIZE, sizeof(mus_float_t));
  470. k = 0;
  471. for (i = 0; i &lt; framples; i++)
  472. {
  473. obuf[0][k] = MUS_FLOAT_TO_SAMPLE(0.1 * sin(phase)); /* amp = .1 */
  474. phase += incr;
  475. k++;
  476. if (k == BUFFER_SIZE)
  477. {
  478. mus_sound_write(fd, 0, BUFFER_SIZE-1, 1, obuf);
  479. k=0;
  480. }
  481. }
  482. if (k &gt; 0) mus_sound_write(fd, 0, k - 1, 1, obuf);
  483. mus_sound_close_output(fd, 22050 * mus_bytes_per_sample(MUS_BSHORT));
  484. free(obuf[0]);
  485. }
  486. return(0);
  487. }
  488. </pre>
  489. <div class="innerheader" id="clmosc">clmosc</div>
  490. <p>This is program uses the clm.c oscillator and output functions to write the same sine wave
  491. as we wrote in SndSine.</p>
  492. <pre>
  493. int main(int argc, char *argv[])
  494. {
  495. int i;
  496. mus_any *osc, *op;
  497. mus_sound_initialize();
  498. osc = mus_make_oscil(440.0, 0.0);
  499. op = mus_make_sample_to_file("test.snd", 1, MUS_BSHORT, MUS_NEXT);
  500. if (op)
  501. for (i = 0; i &lt; 22050; i++)
  502. mus_sample_to_file(op, i, 0, .1 * mus_oscil(osc, 0.0, 0.0));
  503. mus_free(osc);
  504. if (op) mus_free(op);
  505. return(0);
  506. }
  507. </pre>
  508. <p>Here is the fm-violin and a sample with-sound call:</p>
  509. <pre>
  510. static int feq(float x, int i) {return(fabs(x-i)&lt;.00001);}
  511. void fm_violin(float start, float dur, float frequency, float amplitude, float fm_index, mus_any *op)
  512. {
  513. float pervibfrq = 5.0,
  514. ranvibfrq = 16.0,
  515. pervibamp = .0025,
  516. ranvibamp = .005,
  517. noise_amount = 0.0,
  518. noise_frq = 1000.0,
  519. gliss_amp = 0.0,
  520. fm1_rat = 1.0,
  521. fm2_rat = 3.0,
  522. fm3_rat = 4.0,
  523. reverb_amount = 0.0,
  524. degree = 0.0,
  525. distance = 1.0;
  526. float fm_env[] = {0.0, 1.0, 25.0, 0.4, 75.0, 0.6, 100.0, 0.0};
  527. float amp_env[] = {0.0, 0.0, 25.0, 1.0, 75.0, 1.0, 100.0, 0.0};
  528. float frq_env[] = {0.0, -1.0, 15.0, 1.0, 25.0, 0.0, 100.0, 0.0};
  529. int beg = 0, end, easy_case = 0, npartials, i;
  530. float *coeffs, *partials;
  531. float frq_scl, maxdev, logfrq, sqrtfrq, index1, index2, index3, norm;
  532. float vib = 0.0, modulation = 0.0, fuzz = 0.0, indfuzz = 1.0;
  533. mus_any *carrier, *fmosc1, *fmosc2, *fmosc3, *ampf;
  534. mus_any *indf1, *indf2, *indf3, *fmnoi = NULL, *pervib, *ranvib, *frqf = NULL, *loc;
  535. beg = start * mus_srate();
  536. end = beg + dur * mus_srate();
  537. frq_scl = mus_hz_to_radians(frequency);
  538. maxdev = frq_scl * fm_index;
  539. if ((noise_amount == 0.0) &amp;&amp;
  540. (feq(fm1_rat, floor(fm1_rat))) &amp;&amp;
  541. (feq(fm2_rat, floor(fm2_rat))) &amp;&amp;
  542. (feq(fm3_rat, floor(fm3_rat))))
  543. easy_case = 1;
  544. logfrq = log(frequency);
  545. sqrtfrq = sqrt(frequency);
  546. index1 = maxdev * 5.0 / logfrq;
  547. if (index1 &gt; M_PI) index1 = M_PI;
  548. index2 = maxdev * 3.0 * (8.5 - logfrq) / (3.0 + frequency * .001);
  549. if (index2 &gt; M_PI) index2 = M_PI;
  550. index3 = maxdev * 4.0 / sqrtfrq;
  551. if (index3 &gt; M_PI) index3 = M_PI;
  552. if (easy_case)
  553. {
  554. npartials = floor(fm1_rat);
  555. if ((floor(fm2_rat)) &gt; npartials) npartials = floor(fm2_rat);
  556. if ((floor(fm3_rat)) &gt; npartials) npartials = floor(fm3_rat);
  557. npartials++;
  558. partials = (float *)calloc(npartials, sizeof(float));
  559. partials[(int)(fm1_rat)] = index1;
  560. partials[(int)(fm2_rat)] = index2;
  561. partials[(int)(fm3_rat)] = index3;
  562. coeffs = mus_partials_to_polynomial(npartials, partials, 1);
  563. norm = 1.0;
  564. }
  565. else norm = index1;
  566. carrier = mus_make_oscil(frequency, 0.0);
  567. if (easy_case == 0)
  568. {
  569. fmosc1 = mus_make_oscil(frequency * fm1_rat, 0.0);
  570. fmosc2 = mus_make_oscil(frequency * fm2_rat, 0.0);
  571. fmosc3 = mus_make_oscil(frequency * fm3_rat, 0.0);
  572. }
  573. else fmosc1 = mus_make_oscil(frequency, 0.0);
  574. ampf = mus_make_env(amp_env, 4, amplitude, 0.0, 1.0, dur, 0, NULL);
  575. indf1 = mus_make_env(fm_env, 4, norm, 0.0, 1.0, dur, 0, NULL);
  576. if (gliss_amp != 0.0)
  577. frqf = mus_make_env(frq_env, 4, gliss_amp * frq_scl, 0.0, 1.0, dur, 0, NULL);
  578. if (easy_case == 0)
  579. {
  580. indf2 = mus_make_env(fm_env, 4, index2, 0.0, 1.0, dur, 0, NULL);
  581. indf3 = mus_make_env(fm_env, 4, index3, 0.0, 1.0, dur, 0, NULL);
  582. }
  583. pervib = mus_make_triangle_wave(pervibfrq, frq_scl * pervibamp, 0.0);
  584. ranvib = mus_make_rand_interp(ranvibfrq, frq_scl * ranvibamp);
  585. if (noise_amount != 0.0) fmnoi = mus_make_rand(noise_frq, noise_amount * M_PI);
  586. loc = mus_make_locsig(degree, distance, reverb_amount, 1, (mus_any *)op, 0, NULL, MUS_INTERP_LINEAR);
  587. for (i = beg; i &lt; end; i++)
  588. {
  589. if (noise_amount != 0.0) fuzz = mus_rand(fmnoi, 0.0);
  590. if (frqf) vib = mus_env(frqf); else vib = 0.0;
  591. vib += mus_triangle_wave(pervib, 0.0) + mus_rand_interp(ranvib, 0.0);
  592. if (easy_case)
  593. modulation = mus_env(indf1) *
  594. mus_polynomial(coeffs, mus_oscil(fmosc1, vib, 0.0), npartials);
  595. else
  596. modulation = mus_env(indf1) * mus_oscil(fmosc1, (fuzz + fm1_rat * vib), 0.0) +
  597. mus_env(indf2) * mus_oscil(fmosc2, (fuzz + fm2_rat * vib), 0.0) +
  598. mus_env(indf3) * mus_oscil(fmosc3, (fuzz + fm3_rat * vib), 0.0);
  599. mus_locsig(loc, i, mus_env(ampf) * mus_oscil(carrier, vib + indfuzz * modulation, 0.0));
  600. }
  601. mus_free(pervib);
  602. mus_free(ranvib);
  603. mus_free(carrier);
  604. mus_free(fmosc1);
  605. mus_free(ampf);
  606. mus_free(indf1);
  607. if (fmnoi) mus_free(fmnoi);
  608. if (frqf) mus_free(frqf);
  609. if (!(easy_case))
  610. {
  611. mus_free(indf2);
  612. mus_free(indf3);
  613. mus_free(fmosc2);
  614. mus_free(fmosc3);
  615. }
  616. else
  617. free(partials);
  618. mus_free(loc);
  619. }
  620. int main(int argc, char *argv[])
  621. {
  622. mus_any *op = NULL;
  623. mus_sound_initialize();
  624. op = mus_make_sample_to_file("test.snd", 1, MUS_BSHORT, MUS_NEXT);
  625. if (op)
  626. {
  627. fm_violin(0.0, 20.0, 440.0, .3, 1.0, op);
  628. mus_free(op);
  629. }
  630. return(0);
  631. }
  632. </pre>
  633. <p>The CLM version is v.ins, the Scheme version can be found in <a href="sndscm.html#vdoc">v.scm</a>,
  634. and the Ruby version is in v.rb.
  635. This code can be run:</p>
  636. <pre>
  637. cc v.c -o vc -O3 -lm io.o headers.o audio.o sound.o clm.o -DLINUX
  638. </pre>
  639. <p>For generators such as src that take a function for "as-needed" input,
  640. you can use something like:</p>
  641. <pre>
  642. static mus_float_t input_as_needed(void *arg, int dir) {/* get input here &mdash; arg is "sf" passed below */}
  643. static SCM call_phase-vocoder(void)
  644. {
  645. mus_any *pv;
  646. int sf; /* file channel or whatever */
  647. pv = mus_make_phase_vocoder(NULL, 512, 4, 128, 0.5, NULL, NULL, NULL, (void *)sf);
  648. mus_phase_vocoder(pv, &amp;input_as_needed);
  649. /* etc */
  650. }
  651. </pre>
  652. <!--
  653. void src_file(const char *file, double ratio)
  654. {
  655. mus_any **rds, **srcs;
  656. char *temp_out;
  657. const char *comment;
  658. int k, chan, chans, width = 32, out_fd, sample_type, header_type, buffer_size;
  659. mus_long_t samp, old_samps, new_samps;
  660. mus_float_t old_srate, new_srate;
  661. mus_float_t **obufs;
  662. old_srate = mus_srate();
  663. new_srate = mus_sound_srate(file); /* need have no connection with previous CLM srate setting */
  664. mus_set_srate(new_srate);
  665. chans = mus_sound_chans(file);
  666. sample_type = mus_sound_sample_type(file);
  667. header_type = mus_sound_header_type(file);
  668. comment = mus_sound_comment(file);
  669. buffer_size = mus_file_buffer_size();
  670. old_samps = mus_sound_framples(file);
  671. new_samps = old_samps / ratio; /* old-srate/new-srate in-coming */
  672. temp_out = snd_tempnam();
  673. out_fd = mus_sound_open_output(temp_out, new_srate, chans, sample_type, header_type, comment);
  674. srcs = (mus_any **)malloc(chans * sizeof(mus_any *));
  675. rds = (mus_any **)malloc(chans * sizeof(mus_any *));
  676. obufs = (mus_float_t **)malloc(chans * sizeof(mus_float_t));
  677. for (chan = 0; chan < chans; chan++)
  678. {
  679. rds[chan] = mus_make_readin(file, chan, 0, 1);
  680. srcs[chan] = mus_make_src(NULL, ratio, width, (void *)rds[chan]);
  681. obufs[chan] = (mus_float_t *)malloc(buffer_size * sizeof(mus_float_t));
  682. }
  683. for (k = 0, samp = 0; samp < new_samps; samp++)
  684. {
  685. for (chan = 0; chan < chans; chan++)
  686. obufs[chan][k] = MUS_FLOAT_TO_SAMPLE(mus_src(srcs[chan], 0.0, &input_as_needed));
  687. k++;
  688. if (k == buffer_size)
  689. {
  690. mus_sound_write(out_fd, 0, buffer_size - 1, chans, obufs);
  691. k = 0;
  692. }
  693. }
  694. if (k > 0)
  695. mus_sound_write(out_fd, 0, k - 1, chans, obufs);
  696. mus_sound_close_output(out_fd, new_samps * chans * mus_bytes_per_sample(sample_type));
  697. mus_sound_forget(file);
  698. for (chan = 0; chan < chans; chan++)
  699. {
  700. free(obufs[chan]);
  701. mus_free(srcs[chan]);
  702. mus_free(rds[chan]);
  703. }
  704. free(obufs);
  705. free(srcs);
  706. free(rds);
  707. move_file(temp_out, file);
  708. free(temp_out);
  709. mus_set_srate(old_srate);
  710. }
  711. -->
  712. <p>
  713. Michael Scholz
  714. has written a package using these functions, and several CLM instruments:
  715. see the sndins directory, and in particular the README file, for details.
  716. </p>
  717. <div class="innerheader" id="otherexamples">Other examples</div>
  718. <p>The primary impetus for the sound library was the development
  719. of Snd and CLM, both of which are freely available.
  720. </p>
  721. <div class="header" id="sndlibxen">Extension Languages</div>
  722. <p>Much of sndlib is accessible at run time in any program that has one of
  723. the languages supported by the xen package (s7, Ruby, Forth);
  724. the modules sndlib2xen and clm2xen tie most of the library into that language
  725. making it possible to call the library functions from its interpreter. The documentation
  726. is scattered around, unfortunately: the clm side is in sndclm.html and extsnd.html with many
  727. examples in Snd's <a href="sndscm.html#exampdoc">examp.scm</a>. Most of these are obvious translations of the
  728. constants and functions described above into Scheme. To initialize sndlib, call Init_sndlib,
  729. or, at run time, use s7's loader and s7_init_sndlib:
  730. </p>
  731. <pre>
  732. (let ((sndlib (load "libsndlib.so"
  733. (inlet (curlet)
  734. (cons 'init_func 's7_init_sndlib)))))
  735. ....)
  736. </pre>
  737. <p>Init_sndlib ties most of the functions mentioned above into the extension language (s7, Forth, or Ruby).
  738. </p>
  739. <pre>
  740. mus-next mus-aifc mus-rf64 mus-riff mus-nist mus-raw mus-ircam mus-aiff mus-bicsf mus-soundfont mus-voc mus-svx mus-caff
  741. mus-bshort mus-lshort mus-mulaw mus-alaw mus-byte mus-ubyte mus-bfloat
  742. mus-lfloat mus-bint mus-lint mus-b24int mus-l24int mus-bdouble mus-ldouble
  743. mus-ubshort mus-ulshort
  744. mus-sound-samples (filename) samples of sound according to header (can be incorrect)
  745. mus-sound-framples (filename) framples of sound according to header (can be incorrect)
  746. mus-sound-duration (filename) duration of sound in seconds
  747. mus-sound-datum-size (filename) bytes per sample
  748. mus-sound-data-location (filename) location of first sample (bytes)
  749. mus-sound-chans (filename) number of channels (samples are interleaved)
  750. mus-sound-srate (filename) sampling rate
  751. mus-sound-header-type (filename) header type (e.g. mus-aiff)
  752. mus-sound-sample-type (filename) sample type (e.g. mus-bshort)
  753. mus-sound-length (filename) true file length (bytes)
  754. mus-sound-type-specifier (filename) original header type identifier
  755. mus-sound-maxamp(filename) returns a list of max amps and locations thereof
  756. mus-sound-loop-info(filename) returns list of 4 loop values (the actual mark positions here, not
  757. the so-called id's), then base-note and base-detune
  758. mus-header-type-name (type) e.g. "AIFF"
  759. mus-sample-type-name (format) e.g. "16-bit big endian linear"
  760. mus-sound-comment (filename) header comment, if any
  761. mus-sound-write-date (filename) sound write date
  762. sample-type-bytes-per-sample (format) bytes per sample
  763. mus-sound-open-input (filename) open filename (a sound file) returning an integer ("fd" below)
  764. mus-sound-open-output (filename srate chans sample-type header-type comment)
  765. create a new sound file with the indicated attributes, return "fd"
  766. mus-sound-reopen-output (filename chans sample-type header-type data-location)
  767. reopen (without disturbing) filename, ready to be written
  768. mus-sound-close-input (fd) close sound file
  769. mus-sound-close-output (fd bytes) close sound file and update its length indication, if any
  770. mus-sound-read (fd beg end chans sdata) read data from sound file fd loading the data array from beg to end
  771. sdata is a float-vector that should be able to accommodate the read
  772. mus-sound-write (fd beg end chans sdata) write data to sound file fd
  773. mus-sound-seek-frample (fd frample) move to frample in sound file fd
  774. mus-file-clipping (fd) whether output is clipped in file 'fd'
  775. mus-clipping () global clipping choice
  776. mus-oss-set-buffers (num size) in Linux (OSS) sets the number and size of the OSS "fragments"
  777. ;;; this function prints header information
  778. (define info
  779. (lambda (file)
  780. (string-append
  781. file
  782. ": chans: " (number-&gt;string (mus-sound-chans file))
  783. ", srate: " (number-&gt;string (mus-sound-srate file))
  784. ", " (mus-header-type-name (mus-sound-header-type file))
  785. ", " (mus-sample-type-name (mus-sound-sample-type file))
  786. ", len: " (number-&gt;string
  787. (/ (mus-sound-samples file)
  788. (* (mus-sound-chans file) (mus-sound-srate file)))))))
  789. </pre>
  790. <div class="innerheader">s7 repl and sndlib</div>
  791. <pre>
  792. #include &lt;stdlib.h&gt;
  793. #include &lt;stdio.h&gt;
  794. #include &lt;string.h&gt;
  795. #include &lt;unistd.h&gt;
  796. #include "mus-config.h"
  797. #include "s7.h"
  798. #include "xen.h"
  799. #include "clm.h"
  800. #include "clm2xen.h"
  801. static void mus_error_to_s7(int type, char *msg)
  802. {
  803. s7_error(s7, /* s7 is declared in xen.h, defined in xen.c */
  804. s7_make_symbol(s7, "mus-error"),
  805. s7_cons(s7, s7_make_string(s7, msg), s7_nil(s7)));
  806. }
  807. int main(int argc, char **argv)
  808. {
  809. s7 = s7_init();
  810. s7_xen_initialize(s7);
  811. Init_sndlib();
  812. mus_error_set_handler(mus_error_to_s7); /* catch low-level errors and pass them to s7-error */
  813. if (argc == 2)
  814. {
  815. fprintf(stderr, "load %s\n", argv[1]);
  816. s7_load(s7, argv[1]);
  817. }
  818. else
  819. {
  820. s7_load(s7, "repl.scm");
  821. s7_eval_c_string(s7, "((*repl* 'run))");
  822. }
  823. return(0);
  824. }
  825. /* gcc -o sl sl.c /home/bil/test/sndlib/libsndlib.a -Wl,-export-dynamic -lasound -lm -I. -ldl -lgsl -lgslcblas -lfftw3
  826. *
  827. * (load "sndlib-ws.scm")
  828. * (load "v.scm")
  829. * (set! *clm-player* (lambda (file) (system (format #f "sndplay ~A" file))))
  830. * (with-sound (:play #t) (fm-violin 0 1 330 .1))
  831. */
  832. </pre>
  833. <div class="related">
  834. related documentation: &nbsp;
  835. <a href="snd.html">snd.html &nbsp;</a>
  836. <a href="grfsnd.html">grfsnd.html &nbsp;</a>
  837. <a href="extsnd.html">extsnd.html &nbsp;</a>
  838. <a href="sndscm.html">sndscm.html &nbsp;</a>
  839. <a href="sndclm.html">sndclm.html &nbsp;</a>
  840. <a href="s7.html">s7.html &nbsp;</a>
  841. <a href="index.html">index.html</a>
  842. </div>
  843. </body>
  844. </html>