fix multiple plugin runs over same file
- add deinit() functions to help
This commit is contained in:
		
							parent
							
								
									adf89eb360
								
							
						
					
					
						commit
						17ca737291
					
				
					 4 changed files with 46 additions and 39 deletions
				
			
		
							
								
								
									
										8
									
								
								examples/middle_amp.scri
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/middle_amp.scri
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| load :0; | ||||
| amp 5 1 8; | ||||
| amp 7 4 2; | ||||
| amp 80 70 10; | ||||
| amp 80 73 20; | ||||
| amp 80 75 20; | ||||
| amp 80 76 20; | ||||
| quicksave; | ||||
|  | @ -1,4 +0,0 @@ | |||
| load :0; | ||||
| amp 3 1 20; | ||||
| # echo 3 0 1 0.2; | ||||
| quicksave; | ||||
|  | @ -13,6 +13,7 @@ pub const ImageError = error{ | |||
|     UnknownPlugin, | ||||
|     InvalidSymbol, | ||||
|     InstantiateFail, | ||||
|     WriteFail, | ||||
| }; | ||||
| 
 | ||||
| /// Low level integration function with libsndfile. | ||||
|  | @ -41,22 +42,13 @@ fn sopen( | |||
|     return file.?; | ||||
| } | ||||
| 
 | ||||
| ///Read a single frame from a file into an interleaved buffer. | ||||
| ///If more channels are required than are available in the file, the remaining | ||||
| ///channels are distributed in a round-robin fashion (LRLRL). | ||||
| fn sread(file_opt: ?*c.SNDFILE, file_chans: c_int, buf: []f32) bool { | ||||
|     var file = file_opt.?; | ||||
| fn swrite(file: *c.SNDFILE, buf: [*]f32, frames: i64) !void { | ||||
|     const count = c.sf_writef_float(file, buf, frames); | ||||
| 
 | ||||
|     const n_read: c.sf_count_t = c.sf_readf_float(file, buf.ptr, 1); | ||||
|     const buf_chans = @intCast(c_int, buf.len); | ||||
| 
 | ||||
|     var i = file_chans - 1; | ||||
|     while (i < buf_chans) : (i += 1) { | ||||
|         //buf[@intCast(usize, i)] = buf[i % file_chans]; | ||||
|         buf[@intCast(usize, i)] = buf[@intCast(usize, @mod(i, file_chans))]; | ||||
|     if (count != frames) { | ||||
|         std.debug.warn("Wanted to read {}, got {}\n", frames, count); | ||||
|         return ImageError.WriteFail; | ||||
|     } | ||||
| 
 | ||||
|     return n_read == 1; | ||||
| } | ||||
| 
 | ||||
| fn getEndPos(path: []const u8) !usize { | ||||
|  | @ -174,8 +166,7 @@ pub const Image = struct { | |||
|         params: plugins.ParamList, | ||||
|     ) !void { | ||||
|         var ctx = try plugins.makeContext(self.allocator, plugin_uri); | ||||
|         std.debug.warn("\tworld: {}\n", ctx.world); | ||||
|         std.debug.warn("\tplugin: {}\n", ctx.plugin); | ||||
|         defer ctx.deinit(); | ||||
| 
 | ||||
|         var ports = try lv2.setupPorts(&ctx); | ||||
| 
 | ||||
|  | @ -184,6 +175,8 @@ pub const Image = struct { | |||
|             return ImageError.InvalidPlugin; | ||||
|         } | ||||
| 
 | ||||
|         // TODO check n_audio_out | ||||
| 
 | ||||
|         // now, for each param for the plugin, we find its port, and set | ||||
|         // the value for the port there. | ||||
|         var it = params.iterator(); | ||||
|  | @ -213,12 +206,14 @@ pub const Image = struct { | |||
|         // now we need to generate a temporary file and put the output of | ||||
|         // running the plugin on that file | ||||
|         var tmpnam = try temporaryName(self.allocator); | ||||
|         std.debug.warn("temporary name: {}\n", tmpnam); | ||||
|         std.debug.warn("\trunning plugin from '{}' to '{}'\n", self.curpath, tmpnam); | ||||
| 
 | ||||
|         var out_fmt = mkSfInfo(); | ||||
|         var out_file = try sopen(self.allocator, tmpnam, c.SFM_WRITE, &out_fmt); | ||||
| 
 | ||||
|         var rctx = try plugins.RunContext.init(self.allocator, ctx.plugin); | ||||
|         defer rctx.deinit(); | ||||
| 
 | ||||
|         rctx.connectPorts(ports); | ||||
|         lv2.lilv_instance_activate(rctx.instance); | ||||
| 
 | ||||
|  | @ -226,41 +221,41 @@ pub const Image = struct { | |||
|         // just copy the original image and the part where we run the plugin | ||||
|         // over the image. | ||||
| 
 | ||||
|         const end_pos = (try getEndPos(self.path)) - BMPHeaderSize; | ||||
|         std.debug.warn("file end: {}\n", end_pos); | ||||
|         const seek_pos = position.seekPos(end_pos); | ||||
|         const file_end = try getEndPos(self.curpath); | ||||
|         const seek_pos = position.seekPos(file_end); | ||||
|         std.debug.warn("start {} end {}\n", seek_pos.start, seek_pos.end); | ||||
| 
 | ||||
|         var seeked = c.sf_seek(self.sndfile, 0, c.SEEK_SET); | ||||
|         std.debug.warn("in: seek {}\n", seeked); | ||||
| 
 | ||||
|         var i: usize = 0; | ||||
| 
 | ||||
|         while (i < end_pos) : (i += 1) { | ||||
|         while (i < file_end) : (i += 1) { | ||||
|             // if we're still on the bmp header phase, copy bytes | ||||
|             // if we aren't in the range from seek_pos, copy bytes | ||||
|             // if we are in the range, run lilv plugin | ||||
| 
 | ||||
|             // TODO speed this up by not reading byte-by-byte. | ||||
|             // TODO check value of this | ||||
|             _ = c.sf_readf_float(self.sndfile, rctx.in_buf.ptr, 1); | ||||
|             const read_bytes = c.sf_readf_float(self.sndfile, rctx.in_buf.ptr, 1); | ||||
|             if (read_bytes == 0) { | ||||
|                 std.debug.warn("WARN! reached EOF at idx={}\n", i); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             if (i < BMPHeaderSize or !seek_pos.contains(i)) { | ||||
|                 _ = c.sf_writef_float(out_file, rctx.in_buf.ptr, 1); | ||||
|                 try swrite(out_file, rctx.in_buf.ptr, 1); | ||||
|             } else { | ||||
|                 lv2.lilv_instance_run(rctx.instance, 1); | ||||
| 
 | ||||
|                 var count = c.sf_writef_float(out_file, rctx.out_buf.ptr, 1); | ||||
|                 if (count != 1) { | ||||
|                     std.debug.warn( | ||||
|                         "Failed to write to output file at idx {}.\n", | ||||
|                         i, | ||||
|                     ); | ||||
| 
 | ||||
|                     // maybe we return an error? | ||||
|                 } | ||||
|                 try swrite(out_file, rctx.out_buf.ptr, 1); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         c.sf_write_sync(out_file); | ||||
|         _ = c.sf_close(out_file); | ||||
|         _ = c.sf_close(self.sndfile); | ||||
|         self.sndfile = out_file; | ||||
| 
 | ||||
|         // reopen the file as SFM_READ so we can run plugin chains etc | ||||
|         self.sndfile = try sopen(self.allocator, tmpnam, c.SFM_READ, &out_fmt); | ||||
|         self.curpath = tmpnam; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -51,6 +51,10 @@ pub const Context = struct { | |||
|     // they should both be 1. | ||||
|     n_audio_in: usize = 0, | ||||
|     n_audio_out: usize = 0, | ||||
| 
 | ||||
|     pub fn deinit(self: *Context) void { | ||||
|         c.lilv_world_free(self.world); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /// Represents the specific run context of plugin instantation. | ||||
|  | @ -75,6 +79,10 @@ pub const RunContext = struct { | |||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     pub fn deinit(self: *RunContext) void { | ||||
|         c.lilv_instance_free(self.instance); | ||||
|     } | ||||
| 
 | ||||
|     pub fn connectPorts(self: *RunContext, ports: []*lv2.Port) void { | ||||
|         var i: usize = 0; | ||||
|         var o: usize = 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue