Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
simage_libsndfile.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Kongsberg Oil & Gas Technologies
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif /* HAVE_CONFIG_H */
20 
21 #ifdef SIMAGE_LIBSNDFILE_SUPPORT
22 
23 #include <simage.h>
24 #include <simage_private.h>
25 #include <simage_libsndfile.h>
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 
31 #include <sndfile.h>
32 
33 typedef struct {
34  SNDFILE *file;
35  SF_INFO sfinfo;
36  double *tempbuffer;
37  int tempbuffersize;
38 } libsndfile_context;
39 
40 static void
41 libsndfile_init_context(libsndfile_context *context)
42 {
43  context->file = NULL;
44  context->tempbuffer = NULL;
45  context->tempbuffersize = 0;
46 }
47 
48 static void
49 libsndfile_cleanup_context(libsndfile_context *context)
50 {
51  if (context->tempbuffer)
52  free(context->tempbuffer);
53  context->tempbuffer = NULL;
54  context->tempbuffersize = 0;
55 }
56 
57 int
58 libsndfile_stream_open(const char * filename, s_stream * stream,
59  s_params * params)
60 {
61  libsndfile_context *context;
62  FILE *dummyfile;
63 
64  dummyfile = fopen(filename, "rb");
65  if (!dummyfile)
66  return 0;
67  else
68  fclose(dummyfile);
69 
70  context = (libsndfile_context *) malloc(sizeof(libsndfile_context));
71  libsndfile_init_context(context);
72 
73  context->file = sf_open (filename, SFM_READ, &context->sfinfo) ;
74  if (!context->file) {
75  libsndfile_cleanup_context(context);
76  free(context);
77  return 0;
78  }
79  sf_command (context->file, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ;
80 
81  s_stream_context_set(stream, (void *)context);
82 
83  /* FIXME: SF_INFO::frames is of type sf_count_t, which is a 32bit
84  integer in some libsndfile version and 64bit on others (like the
85  Mac OS X one), so casting context->sfinfo.frames to int is not
86  totally correct - but necessary, since we do not have a 64bit
87  s_params type.
88  20030108 kyrah
89  */
91  "samplerate", S_INTEGER_PARAM_TYPE, context->sfinfo.samplerate,
92  "frames", S_INTEGER_PARAM_TYPE, (int) context->sfinfo.frames,
93  "channels", S_INTEGER_PARAM_TYPE, context->sfinfo.channels,
94  NULL);
95 
96  return 1;
97 }
98 
99 void *
100 libsndfile_stream_get(s_stream * stream, void * buffer, int * size, s_params * params)
101 {
102  int itemsread;
103  libsndfile_context *context;
104  int items;
105  int itemssize;
106  int i;
107  short int *intbuffer;
108 
109  context = (libsndfile_context *)s_stream_context_get(stream);
110 
111  if (context != NULL) {
112  /* fixme 20020924 thammer : support other (return) formats
113  * than 16 bit signed. This should be very little work!
114  */
115 
116  /*
117  * size must be an integer multiple of bytespersample*channels
118  */
119 
120  if ( (*size) % (2 * context->sfinfo.channels) ) {
121  *size = 0;
122  return NULL;
123  }
124 
125  items = *size / 2;
126  itemssize = items*sizeof(double);
127 
128  if (context->tempbuffersize < itemssize) {
129  if (context->tempbuffer)
130  free(context->tempbuffer);
131  context->tempbuffer = (double *)malloc(itemssize);
132  }
133 
134  intbuffer = (short int*)buffer;
135  itemsread = sf_read_double(context->file, context->tempbuffer, items);
136  for (i=0; i<itemsread; i++) {
137  intbuffer[i] = context->tempbuffer[i] * (double)32767.0;
138  }
139 
140  if (itemsread > 0) {
141  *size = itemsread * 2;
142  return buffer;
143  }
144 
145  /* fixme 20020924 thammer: check params for conversion requests
146  */
147  }
148  *size = 0;
149  return NULL;
150 }
151 
152 void
154 {
155  libsndfile_context *context;
156  context = (libsndfile_context *)s_stream_context_get(stream);
157  if (context != NULL) {
158  sf_close(context->file);
159  context->file = NULL;
160  }
161  libsndfile_cleanup_context(context);
162  free(context);
163 }
164 
165 int
166 libsndfile_stream_seek(s_stream * stream, int offset, int whence,
167  s_params *params)
168 {
169  libsndfile_context *context;
170  context = (libsndfile_context *)s_stream_context_get(stream);
171  if (context != NULL) {
172  return sf_seek(context->file, offset, whence);
173  }
174  else
175  return -1;
176 }
177 
178 int
179 libsndfile_stream_tell(s_stream * stream, s_params *params)
180 {
181  libsndfile_context *context;
182  context = (libsndfile_context *)s_stream_context_get(stream);
183  if (context != NULL) {
184  return sf_seek(context->file, 0, SEEK_CUR);
185  }
186  else
187  return -1;
188 }
189 
190 #endif /* SIMAGE_LIBSNDFILE_SUPPORT */
void s_params_set(s_params *params,...)
Definition: params.c:187
void s_stream_context_set(s_stream *stream, void *context)
Definition: stream.c:219
int libsndfile_stream_tell(s_stream *stream, s_params *params)
void * libsndfile_stream_get(s_stream *stream, void *buffer, int *size, s_params *params)
Windows specific information.
int libsndfile_stream_open(const char *filename, s_stream *stream, s_params *params)
void * s_stream_context_get(s_stream *stream)
Definition: stream.c:213
s_params * s_stream_params(s_stream *stream)
Definition: stream.c:204
void libsndfile_stream_close(s_stream *stream)
int libsndfile_stream_seek(s_stream *stream, int offset, int whence, s_params *params)