Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / bin / edje_multisense_convert.c
1 #include "edje_multisense_convert.h"
2
3 #ifdef HAVE_LIBSNDFILE
4 # define READBUF 1024
5 # ifdef HAVE_VORBIS
6 #  include <vorbis/vorbisenc.h>
7 # endif
8
9 # ifdef HAVE_LIBFLAC
10 #  include <FLAC/metadata.h>
11 #  include <FLAC/stream_encoder.h>
12 # endif
13
14 Edje_Sound_Encode *
15 _edje_multisense_encode(const char *filename, Edje_Sound_Sample *sample, double quality __UNUSED__)
16 {
17    SF_INFO sfinfo;
18    SNDFILE* sfile;
19    Edje_Sound_Encode *enc_info;
20    
21    enc_info = calloc(1, sizeof(Edje_Sound_Encode));
22    if (!enc_info)
23      {
24         ERR("while allocating memory to load file ");
25         exit(-1);
26      }
27    memset (&sfinfo, 0, sizeof (SF_INFO));
28    
29    enc_info->encoded = EINA_FALSE;
30    enc_info->comp_type = "RAW PCM";
31    
32    // Open wav file using sndfile
33    sfile = sf_open (filename, SFM_READ, &sfinfo);
34    if (!sfile)
35      {
36         ERR("Unable to open audio file: %s", filename);
37         exit(-1);
38      }
39
40    if (!sf_format_check(&sfinfo))
41      {
42         ERR("Unknown file, not a valid audio file");
43         exit(-1);
44      }
45
46    if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_COMP)
47      {
48         sf_close(sfile);
49 #ifdef HAVE_LIBFLAC
50         //encode provided wav file to flac
51         enc_info->file = _edje_multisense_encode_to_flac((char *)filename, sfinfo);
52         if (enc_info->file)
53           {
54              enc_info->comp_type = "FLAC";
55              enc_info->encoded = EINA_TRUE;
56           }
57 #else
58         WRN("WARNING: Unable to encode sound %s to FLAC compression",
59             sample->name);
60 #endif
61      }
62    else if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY)
63      {
64         sf_close(sfile);
65 #ifdef HAVE_VORBIS
66         //encode provided wav file to ogg-vorbis
67         enc_info->file = _edje_multisense_encode_to_ogg_vorbis((char *)filename,
68                                                                quality, sfinfo);
69         if (enc_info->file)
70           {
71              enc_info->comp_type = "OGG-VORBIS";
72              enc_info->encoded = EINA_TRUE;
73           }
74 #else
75         WRN("WARNING: Unable to encode sound %s to Ogg-Vorbis",
76             sample->name);
77 #endif
78      }
79    else
80      eina_stringshare_replace(&enc_info->file, filename);
81    return enc_info;
82 }
83
84 #ifdef HAVE_LIBFLAC
85 const char*
86 _edje_multisense_encode_to_flac(char *snd_path, SF_INFO sfinfo)
87 {
88    unsigned int total_samples = 0; /* can use a 32-bit number due to WAVE size limitations */
89    FLAC__bool ok = 1;
90    FLAC__StreamEncoder *encoder = 0;
91    FLAC__StreamEncoderInitStatus init_status;
92    FLAC__StreamMetadata *metadata[2];
93    FLAC__StreamMetadata_VorbisComment_Entry entry;
94    SNDFILE *sfile;
95    sf_count_t size;
96    char *tmp;
97
98    sfile = sf_open(snd_path, SFM_READ, &sfinfo);
99    if (!sfile) return NULL;
100    if (!sf_format_check(&sfinfo))
101      {
102         sf_close(sfile);
103         return NULL;
104      }
105    size = sf_seek(sfile, 0, SEEK_END);
106    sf_seek(sfile, 0, SEEK_SET);
107    tmp = malloc(strlen(snd_path) + 1 + 5);
108    if (!tmp)
109      {
110         sf_close(sfile);
111         return NULL;
112      }
113    strcpy(tmp, snd_path);
114    snd_path = tmp;
115    strcat(snd_path, ".flac");
116
117    total_samples = size;
118
119    /* allocate the encoder */
120    if ((encoder = FLAC__stream_encoder_new()) == NULL)
121      {
122         ERR("ERROR: Creating FLAC encoder\n");
123         free(snd_path);
124         sf_close(sfile);
125         return NULL;
126      }
127
128    /* Verify it's own encoded output. This will slow the encoding process. */
129    ok &= FLAC__stream_encoder_set_verify(encoder, 1);
130
131    //Levels range from 0 (fastest, least compression) to 8 (slowest, most compression).
132    //A value larger than 8 will be treated as 8.
133    //5 is used for good compression and moderate compression/decompression speed.
134    ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
135    ok &= FLAC__stream_encoder_set_channels(encoder, sfinfo.channels);
136    ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, 16);
137    ok &= FLAC__stream_encoder_set_sample_rate(encoder, sfinfo.samplerate);
138    ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples);
139
140    /* now add some metadata; we'll add some tags and a padding block */
141    if (ok)
142      {
143         if ((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL
144             || (metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL
145             || !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "Encoder", "flac")
146             || !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, 0))
147           {
148              ERR("ERROR: out of memory error or tag error\n");
149              ok = 0;
150           }
151         metadata[1]->length = 16; /* set the padding length */
152         ok = FLAC__stream_encoder_set_metadata(encoder, metadata, 2);
153      }
154
155    /* initialize encoder */
156    if (ok)
157      {
158         init_status = FLAC__stream_encoder_init_file(encoder, snd_path, NULL,
159                                                      (void *)(long)(total_samples));
160         if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
161           {
162              ERR("ERROR: unable to initialize FLAC encoder: %s\n",
163                  FLAC__StreamEncoderInitStatusString[init_status]);
164              ok = 0;
165           }
166      }
167    
168    /* read blocks of samples from WAVE file and feed to encoder */
169    while (ok)
170      {
171         FLAC__int32 readbuffer[READBUF * 2];
172         sf_count_t count;
173         int i;
174         
175         count = sf_readf_int(sfile, readbuffer, READBUF);
176         if (count <= 0) break;
177         for (i = 0; i < (count * sfinfo.channels); i++)
178           readbuffer[i] = readbuffer[i] >> 16;
179         ok = FLAC__stream_encoder_process_interleaved(encoder, readbuffer,
180                                                       count);
181      }
182
183    FLAC__stream_encoder_finish(encoder);
184    /* now that encoding is finished, the metadata can be freed */
185    FLAC__metadata_object_delete(metadata[0]);
186    FLAC__metadata_object_delete(metadata[1]);
187
188    FLAC__stream_encoder_delete(encoder);
189    sf_close(sfile);
190    return (snd_path);
191 }
192 #endif
193
194 #ifdef HAVE_VORBIS
195 const char *
196 _edje_multisense_encode_to_ogg_vorbis(char *snd_path, double quality, SF_INFO sfinfo)
197 {
198    ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
199    ogg_page og; /* one Ogg bitstream page.  Vorbis packets are inside */
200    ogg_packet op; /* one raw packet of data for decode */
201    vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */
202    vorbis_comment vc; /* struct that stores all the user comments */
203    vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
204    vorbis_block vb; /* local working space for packet->PCM decode */
205    int eos = 0, ret;
206    char *tmp;
207    SNDFILE *sfile;
208    FILE *fout;
209
210    sfile = sf_open(snd_path, SFM_READ, &sfinfo);
211    if (!sfile) return NULL;
212    if (!sf_format_check(&sfinfo))
213      {
214         sf_close(sfile);
215         return NULL;
216      }
217    tmp = malloc(strlen(snd_path) + 1 + 4);
218    if (!tmp)
219      {
220         sf_close(sfile);
221         return NULL;
222      }
223    strcpy(tmp, snd_path);
224    snd_path = tmp;
225    strcat(snd_path, ".ogg");
226    fout = fopen(snd_path, "wb");
227    if (!fout)
228      {
229         free(snd_path);
230         sf_close(sfile);
231         return NULL;
232      }
233
234    /********** Encode setup ************/
235    vorbis_info_init(&vi);
236    ret = vorbis_encode_init(&vi, sfinfo.channels, sfinfo.samplerate, 
237                             -1, (long)(quality * 1000), -1);
238    if (ret == OV_EFAULT) printf("OV_EFAULT\n");
239    if (ret == OV_EINVAL) printf("OV_EINVAL\n");
240    if (ret == OV_EIMPL) printf("OV_EIMPL\n");
241
242    if (ret)
243      {
244         fclose(fout);
245         free(snd_path);
246         sf_close(sfile);
247         return NULL;
248      }
249
250    /* add a comment */
251    vorbis_comment_init(&vc);
252    vorbis_comment_add_tag(&vc, "", "");
253
254    /* set up the analysis state and auxiliary encoding storage */
255    vorbis_analysis_init(&vd, &vi);
256    vorbis_block_init(&vd, &vb);
257
258    srand(time(NULL));
259    ogg_stream_init(&os, rand());
260
261    ogg_packet header;
262    ogg_packet header_comm;
263    ogg_packet header_code;
264
265    vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);
266    ogg_stream_packetin(&os, &header); /* automatically placed in its own page */
267    ogg_stream_packetin(&os, &header_comm);
268    ogg_stream_packetin(&os, &header_code);
269
270    while (!eos)
271      {
272         int result = ogg_stream_flush(&os, &og);
273         if (!result) break;
274         fwrite(og.header, 1, og.header_len, fout);
275         fwrite(og.body, 1, og.body_len, fout);
276      }
277
278    while (!eos)
279      {
280         int i, ch;
281         float readbuffer[READBUF * 2];
282         sf_count_t count;
283         
284         count = sf_readf_float(sfile, readbuffer, READBUF);
285
286         if (!count)
287           vorbis_analysis_wrote(&vd, 0);
288         else
289           {
290              float **buffer = vorbis_analysis_buffer(&vd, count);
291              
292              /* uninterleave samples */
293              for (i = 0; i < count; i++)
294                {
295                   for (ch = 0; ch < sfinfo.channels; ch++)
296                     buffer[ch][i]= readbuffer[(i * sfinfo.channels) + ch];
297                }
298              vorbis_analysis_wrote(&vd, i);
299           }
300         while (vorbis_analysis_blockout(&vd, &vb) == 1)
301           {
302              vorbis_analysis(&vb, NULL);
303              vorbis_bitrate_addblock(&vb);
304
305              while (vorbis_bitrate_flushpacket(&vd, &op))
306                {
307                   ogg_stream_packetin(&os, &op);
308                   while (!eos)
309                     {
310                        int result = ogg_stream_pageout(&os, &og);
311                        if (!result) break;
312                        fwrite(og.header, 1, og.header_len, fout);
313                        fwrite(og.body, 1, og.body_len, fout);
314                        if (ogg_page_eos(&og)) eos = 1;
315                     }
316                }
317           }
318      }
319    ogg_stream_clear(&os);
320    vorbis_block_clear(&vb);
321    vorbis_dsp_clear(&vd);
322    vorbis_comment_clear(&vc);
323    vorbis_info_clear(&vi);
324    sf_close(sfile);
325    fclose (fout);
326    return snd_path;
327 }
328 #endif
329 #endif